Современное производство стали использует большое количество электрической энергии. Большая её часть идёт на нагрев и плавление сырья и вспомогательных реагентов, а также на поддержание температуры расплава на заданном уровне. Снижение уровня потребления электроэнергии позволит снизить расходы на неё, что приведёт к сокращению затрат на производство стали, снижению её себестоимости и, как следствие, повышению конкурентоспособности продукции металлургического предприятия.
Сталелитейное производство включает в себя процессы получения металлов из руд или других видов сырья, изменения их химического состава, структуры и свойств, а также последующее производство разнообразных металлических изделий из них. Основными этапами производства являются:
Одним из способов внепечной обработки стали, которая выполняется после выпуска расплава из плавильного агрегата, является легирование в ковше-печи (сталеразливочном ковше). Агрегат ковш-печь — это специальное металлургическое оборудование, которое используется для слива стали, её легирования, последующей транспортировки и разливки в слябы или другие формы. Он представляет собой объёмный металлический резервуар цилиндрической формы, изнутри футерованный огнеупорным кирпичом и снабжённый крышкой.
Легирование стали в ковше-печи происходит путём добавления легирующих материалов в расплав стали через отверстия в крышке ковша: через воронку подаются сыпучие материалы (металлы, неметаллы, а также сплавы), через трайб-аппарат подаются сыпучие или металлические проволоки.
Перемешивание расплава осуществляется продувкой через него инертного газа (азота или, чаще всего, аргона), подаваемого через установленные в днище ковша огнеупорные пробки или через отверстие (фурму) в крышке ковша. Продувка расплава инертным газом улучшает диффузию легирующих добавок в объём сплава, способствует удалению газовых включений и летучих примесей, помогает снижать температуру расплава.
Подогрев расплава осуществляется с помощью графитированных электродов, которые опускают к поверхности расплава через отверстия в крышке ковша. На электроды подаётся напряжение, образуется электрическая дуга, которая и передаёт электроэнергию расплаву.
Поскольку в процессе легирования стали протекают два конкурирующих процесса — нагрев расплава и его остывание, неотъемлемой частью стадии легирования является контроль температуры расплава. От температуры зависит растворимость легирующих добавок и их равномерное распределение в объёме расплавленной стали. Кроме того, регулирование температуры сплава позволяет добиться формирования структуры стали. Поэтому необходимо измерять температуру для того, чтобы, во-первых, определить готовность расплава к введению легирующих добавок и, во-вторых, определить готовность расплава к розливу и формованию или передачи его на доводку.
Температуру расплава в ковше-печи измеряют путём погружения в расплав термоэлектрического преобразователя (термопары) через специальное отверстие для термопар в крышке ковша-печи. Температуру расплава измеряют перед первым, а также перед каждым последующим введением легирующей добавки (в форме сыпучего материала или проволоки) и по окончании процесса легирования.
Процедура измерения температуры расплава затратная по времени: термопару необходимо опустить в ковш, термостатировать в расплаве и извлечь из ковша, чтобы продолжить легирование (добавлять сыпучие и проволочные материалы, перемешивать, подогревать расплав). А поскольку таких замеров температуры в ходе легирования при производстве одной партии стали может быть несколько, то и суммарное время, затрачиваемое на процедуру измерения температуры, может быть существенным.
В течение времени, когда расплав не подогревают, он теряет тепло, его температура снижается. Чтобы повысить температуру до требуемого уровня, расходуют электроэнергию. Чем больше времени расплав теряет энергию, тем больше энергии ему нужно сообщить.
Уменьшение времени, необходимого для измерения температуры расплава, позволяет снизить энергопотребление. Если процесс легирования на предприятии отлажен и воспроизводится с достаточно высокой точностью (подаются точно рассчитанные количества легирующих добавок, инертного газа и производится достаточный нагрев электродами), может быть принято решение об ослаблении промежуточного контроля температуры. Замер температуры может производиться только перед началом процесса легирования. Но поскольку необходимо знать температуру расплава, выходящего со стадии легирования, то вместо непосредственного её измерения можно использовать алгоритмы машинного обучения, которые по известной начальной температуре, сведениях о вносимых добавках, объёме пропускаемого газа и количестве переданной электроэнергии для подогрева расплава позволят предсказать конечную температуру.
В нашем распоряжении находятся данные о параметрах стадии легирования. Для каждой выпускаемой партии стали доступны сведения о поданных легирующих добавках, инертном газе, работе электродах и результатах измерения температуры.
Цель проекта: построить модель, прогнозирующую температуру расплава стали после окончания стадии легирования.
Задачи проекта:
Внимание! Для корректной работы кода в ячейках рекомендуется предварительно установить следующие библиотеки:
!pip install scikit-learn --upgrade -q
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.8/10.8 MB 117.4 MB/s eta 0:00:00
!pip install lightgbm -q
!pip install catboost -q
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 98.7/98.7 MB 8.7 MB/s eta 0:00:00
!pip install xgboost -q
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import sys
import os
import re
import warnings
from sklearn.model_selection import (train_test_split,
RandomizedSearchCV,
cross_val_score)
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler
from sklearn.base import BaseEstimator, RegressorMixin
from sklearn.dummy import DummyRegressor
from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge, Lasso
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from catboost import CatBoostRegressor
from lightgbm import LGBMRegressor
from xgboost import XGBRegressor
from sklearn.metrics import mean_absolute_error
pd.set_option('display.max_columns', None)
np.set_printoptions(threshold=sys.maxsize)
warnings.filterwarnings('ignore')
RANDOM_STATE = 250923
Все данные хранятся в семи файлах.
Файлы данных имеют формат CSV.
PATHS = [r'C:\Users\Георгий\Documents\DS_projects', '/datasets', '/content']
def read_df(name, paths=PATHS):
'''
Функция загрузки данных из CSV-файлов
с проверкой существования пути к файлу.
Принимает название файла.
Возвращает набор данных из файла.
'''
for path in paths:
file_path = os.path.join(path, name)
if os.path.exists(file_path):
df = pd.read_csv(file_path)
return df
print(f'{name}: Something is wrong')
data_arc = read_df('data_arc_new.csv')
data_bulk = read_df('data_bulk_new.csv')
data_bulk_time = read_df('data_bulk_time_new.csv')
data_gas = read_df('data_gas_new.csv')
data_temp = read_df('data_temp_new.csv')
data_wire = read_df('data_wire_new.csv')
data_wire_time = read_df('data_wire_time_new.csv')
Предварительно зададим функции, позволяющие получить основные сведения о наборах данных, отслеживать в наборах данных наличие пропусков и визуализировать их распределение.
def df_info(data):
'''
Функция выводит описание набора данных, первые и посление строки,
а также типы данных набора данных.
Принимает набор исследуемых данных.
'''
display(data.head(2))
display(data.tail(2))
print('Размер набора данных:', data.shape)
print('\nКоличество элементов данных:', data.size)
print('\nКоличество дубликатов в наименованиях признаков:',
data.columns.duplicated().sum())
print('\nУникальные наименования признаков:\n',
data.columns.sort_values().tolist())
print('\nКоличество пропущенных значений:',
data.isna().sum().sum())
print('\nПроцент пропущенных значений:',
round(data.isna().sum().sum() / data.size * 100, 1), '%')
print('\nТипы данных набора данных:')
display(data.dtypes.value_counts())
def show_na(data):
'''
Функция выводит количество пропусков в признаках и
долю пропусков (в процентах) от общего числа записей.
Принимает набор исследуемых данных.
Возвращает датафрейм с описанием распределения пропусков.
'''
total = data.isna().sum().sort_values(ascending=False)
percent = (data.isna().sum() /
data.isna().count() * 100).round(1).sort_values(ascending=False)
df = pd.concat([total, percent], axis=1, keys=['Всего пропусков', '%'])
return df
def pic_na(data):
'''
Функция визуализирует распределение пропусков в наборе данных.
Принимает набор исследуемых данных.
'''
sns.heatmap(data.isna(), cmap=sns.color_palette(['#000000', '#ffffff']))
plt.title('Тепловая карта распределения пропущенных значений')
plt.xlabel('Название признака')
plt.ylabel('Номер записи')
plt.show()
df_info(data_arc)
| key | Начало нагрева дугой | Конец нагрева дугой | Активная мощность | Реактивная мощность | |
|---|---|---|---|---|---|
| 0 | 1 | 2019-05-03 11:02:14 | 2019-05-03 11:06:02 | 0.305130 | 0.211253 |
| 1 | 1 | 2019-05-03 11:07:28 | 2019-05-03 11:10:33 | 0.765658 | 0.477438 |
| key | Начало нагрева дугой | Конец нагрева дугой | Активная мощность | Реактивная мощность | |
|---|---|---|---|---|---|
| 14874 | 3241 | 2019-09-06 17:21:58 | 2019-09-06 17:22:55 | 0.530267 | 0.361543 |
| 14875 | 3241 | 2019-09-06 17:24:54 | 2019-09-06 17:26:15 | 0.389057 | 0.251347 |
Размер набора данных: (14876, 5) Количество элементов данных: 74380 Количество дубликатов в наименованиях признаков: 0 Уникальные наименования признаков: ['key', 'Активная мощность', 'Конец нагрева дугой', 'Начало нагрева дугой', 'Реактивная мощность'] Количество пропущенных значений: 0 Процент пропущенных значений: 0.0 % Типы данных набора данных:
object 2 float64 2 int64 1 dtype: int64
show_na(data_arc)
| Всего пропусков | % | |
|---|---|---|
| key | 0 | 0.0 |
| Начало нагрева дугой | 0 | 0.0 |
| Конец нагрева дугой | 0 | 0.0 |
| Активная мощность | 0 | 0.0 |
| Реактивная мощность | 0 | 0.0 |
Данные об электродах
df_info(data_bulk)
| key | Bulk 1 | Bulk 2 | Bulk 3 | Bulk 4 | Bulk 5 | Bulk 6 | Bulk 7 | Bulk 8 | Bulk 9 | Bulk 10 | Bulk 11 | Bulk 12 | Bulk 13 | Bulk 14 | Bulk 15 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | NaN | NaN | NaN | 43.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 206.0 | NaN | 150.0 | 154.0 |
| 1 | 2 | NaN | NaN | NaN | 73.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 206.0 | NaN | 149.0 | 154.0 |
| key | Bulk 1 | Bulk 2 | Bulk 3 | Bulk 4 | Bulk 5 | Bulk 6 | Bulk 7 | Bulk 8 | Bulk 9 | Bulk 10 | Bulk 11 | Bulk 12 | Bulk 13 | Bulk 14 | Bulk 15 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3127 | 3240 | NaN | NaN | NaN | NaN | NaN | 26.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 192.0 | 54.0 |
| 3128 | 3241 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 180.0 | 52.0 |
Размер набора данных: (3129, 16) Количество элементов данных: 50064 Количество дубликатов в наименованиях признаков: 0 Уникальные наименования признаков: ['Bulk 1', 'Bulk 10', 'Bulk 11', 'Bulk 12', 'Bulk 13', 'Bulk 14', 'Bulk 15', 'Bulk 2', 'Bulk 3', 'Bulk 4', 'Bulk 5', 'Bulk 6', 'Bulk 7', 'Bulk 8', 'Bulk 9', 'key'] Количество пропущенных значений: 35776 Процент пропущенных значений: 71.5 % Типы данных набора данных:
float64 15 int64 1 dtype: int64
show_na(data_bulk)
| Всего пропусков | % | |
|---|---|---|
| Bulk 8 | 3128 | 100.0 |
| Bulk 13 | 3111 | 99.4 |
| Bulk 9 | 3110 | 99.4 |
| Bulk 2 | 3107 | 99.3 |
| Bulk 7 | 3104 | 99.2 |
| Bulk 5 | 3052 | 97.5 |
| Bulk 10 | 2953 | 94.4 |
| Bulk 11 | 2952 | 94.3 |
| Bulk 1 | 2877 | 91.9 |
| Bulk 6 | 2553 | 81.6 |
| Bulk 4 | 2115 | 67.6 |
| Bulk 3 | 1831 | 58.5 |
| Bulk 15 | 881 | 28.2 |
| Bulk 12 | 679 | 21.7 |
| Bulk 14 | 323 | 10.3 |
| key | 0 | 0.0 |
pic_na(data_bulk)
Данные о подаче сыпучих материалов (масса)
key.Bulk 12, Bulk 14, Bulk 15 — менее 30 % пропусков,Bulk 2, Bulk 5, Bulk 7, Bulk 9, Bulk 13, а в признаке Bulk 8 содержится только одно значение.df_info(data_bulk_time)
| key | Bulk 1 | Bulk 2 | Bulk 3 | Bulk 4 | Bulk 5 | Bulk 6 | Bulk 7 | Bulk 8 | Bulk 9 | Bulk 10 | Bulk 11 | Bulk 12 | Bulk 13 | Bulk 14 | Bulk 15 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | NaN | NaN | NaN | 2019-05-03 11:28:48 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 2019-05-03 11:24:31 | NaN | 2019-05-03 11:14:50 | 2019-05-03 11:10:43 |
| 1 | 2 | NaN | NaN | NaN | 2019-05-03 11:36:50 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 2019-05-03 11:53:30 | NaN | 2019-05-03 11:48:37 | 2019-05-03 11:44:39 |
| key | Bulk 1 | Bulk 2 | Bulk 3 | Bulk 4 | Bulk 5 | Bulk 6 | Bulk 7 | Bulk 8 | Bulk 9 | Bulk 10 | Bulk 11 | Bulk 12 | Bulk 13 | Bulk 14 | Bulk 15 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3127 | 3240 | NaN | NaN | NaN | NaN | NaN | 2019-09-06 16:24:28 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 2019-09-06 16:07:29 | 2019-09-06 16:01:34 |
| 3128 | 3241 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 2019-09-06 17:26:33 | 2019-09-06 17:23:15 |
Размер набора данных: (3129, 16) Количество элементов данных: 50064 Количество дубликатов в наименованиях признаков: 0 Уникальные наименования признаков: ['Bulk 1', 'Bulk 10', 'Bulk 11', 'Bulk 12', 'Bulk 13', 'Bulk 14', 'Bulk 15', 'Bulk 2', 'Bulk 3', 'Bulk 4', 'Bulk 5', 'Bulk 6', 'Bulk 7', 'Bulk 8', 'Bulk 9', 'key'] Количество пропущенных значений: 35776 Процент пропущенных значений: 71.5 % Типы данных набора данных:
object 15 int64 1 dtype: int64
show_na(data_bulk_time)
| Всего пропусков | % | |
|---|---|---|
| Bulk 8 | 3128 | 100.0 |
| Bulk 13 | 3111 | 99.4 |
| Bulk 9 | 3110 | 99.4 |
| Bulk 2 | 3107 | 99.3 |
| Bulk 7 | 3104 | 99.2 |
| Bulk 5 | 3052 | 97.5 |
| Bulk 10 | 2953 | 94.4 |
| Bulk 11 | 2952 | 94.3 |
| Bulk 1 | 2877 | 91.9 |
| Bulk 6 | 2553 | 81.6 |
| Bulk 4 | 2115 | 67.6 |
| Bulk 3 | 1831 | 58.5 |
| Bulk 15 | 881 | 28.2 |
| Bulk 12 | 679 | 21.7 |
| Bulk 14 | 323 | 10.3 |
| key | 0 | 0.0 |
pic_na(data_bulk_time)
Данные о подаче сыпучих материалов (время)
key.Bulk 12, Bulk 14, Bulk 15 — менее 30 % пропусков,Bulk 2, Bulk 5, Bulk 7, Bulk 9, Bulk 13, а в признаке Bulk 8 содержится только одно значение,df_info(data_wire)
| key | Wire 1 | Wire 2 | Wire 3 | Wire 4 | Wire 5 | Wire 6 | Wire 7 | Wire 8 | Wire 9 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 60.059998 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1 | 2 | 96.052315 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key | Wire 1 | Wire 2 | Wire 3 | Wire 4 | Wire 5 | Wire 6 | Wire 7 | Wire 8 | Wire 9 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 3079 | 3240 | 34.070400 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3080 | 3241 | 63.117595 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
Размер набора данных: (3081, 10) Количество элементов данных: 30810 Количество дубликатов в наименованиях признаков: 0 Уникальные наименования признаков: ['Wire 1', 'Wire 2', 'Wire 3', 'Wire 4', 'Wire 5', 'Wire 6', 'Wire 7', 'Wire 8', 'Wire 9', 'key'] Количество пропущенных значений: 23385 Процент пропущенных значений: 75.9 % Типы данных набора данных:
float64 9 int64 1 dtype: int64
show_na(data_wire)
| Всего пропусков | % | |
|---|---|---|
| Wire 5 | 3080 | 100.0 |
| Wire 7 | 3070 | 99.6 |
| Wire 4 | 3067 | 99.5 |
| Wire 8 | 3062 | 99.4 |
| Wire 9 | 3052 | 99.1 |
| Wire 3 | 3018 | 98.0 |
| Wire 6 | 3008 | 97.6 |
| Wire 2 | 2002 | 65.0 |
| Wire 1 | 26 | 0.8 |
| key | 0 | 0.0 |
pic_na(data_wire)
Данные о проволочных материалах (масса)
key.Wire 1,Wire 2,Wire 5 содержится только одно значение.df_info(data_wire_time)
| key | Wire 1 | Wire 2 | Wire 3 | Wire 4 | Wire 5 | Wire 6 | Wire 7 | Wire 8 | Wire 9 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2019-05-03 11:06:19 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1 | 2 | 2019-05-03 11:36:50 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| key | Wire 1 | Wire 2 | Wire 3 | Wire 4 | Wire 5 | Wire 6 | Wire 7 | Wire 8 | Wire 9 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 3079 | 3240 | 2019-09-06 15:33:55 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3080 | 3241 | 2019-09-06 17:10:06 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
Размер набора данных: (3081, 10) Количество элементов данных: 30810 Количество дубликатов в наименованиях признаков: 0 Уникальные наименования признаков: ['Wire 1', 'Wire 2', 'Wire 3', 'Wire 4', 'Wire 5', 'Wire 6', 'Wire 7', 'Wire 8', 'Wire 9', 'key'] Количество пропущенных значений: 23385 Процент пропущенных значений: 75.9 % Типы данных набора данных:
object 9 int64 1 dtype: int64
show_na(data_wire_time)
| Всего пропусков | % | |
|---|---|---|
| Wire 5 | 3080 | 100.0 |
| Wire 7 | 3070 | 99.6 |
| Wire 4 | 3067 | 99.5 |
| Wire 8 | 3062 | 99.4 |
| Wire 9 | 3052 | 99.1 |
| Wire 3 | 3018 | 98.0 |
| Wire 6 | 3008 | 97.6 |
| Wire 2 | 2002 | 65.0 |
| Wire 1 | 26 | 0.8 |
| key | 0 | 0.0 |
pic_na(data_wire_time)
Данные о проволочных материалах (время)
key.Wire 1,Wire 2,Wire 5 содержится только одно значение,df_info(data_gas)
| key | Газ 1 | |
|---|---|---|
| 0 | 1 | 29.749986 |
| 1 | 2 | 12.555561 |
| key | Газ 1 | |
|---|---|---|
| 3237 | 3240 | 11.863103 |
| 3238 | 3241 | 12.680959 |
Размер набора данных: (3239, 2) Количество элементов данных: 6478 Количество дубликатов в наименованиях признаков: 0 Уникальные наименования признаков: ['key', 'Газ 1'] Количество пропущенных значений: 0 Процент пропущенных значений: 0.0 % Типы данных набора данных:
int64 1 float64 1 dtype: int64
show_na(data_gas)
| Всего пропусков | % | |
|---|---|---|
| key | 0 | 0.0 |
| Газ 1 | 0 | 0.0 |
Данные о продувке сплава газом
df_info(data_temp)
| key | Время замера | Температура | |
|---|---|---|---|
| 0 | 1 | 2019-05-03 11:02:04 | 1571.0 |
| 1 | 1 | 2019-05-03 11:07:18 | 1604.0 |
| key | Время замера | Температура | |
|---|---|---|---|
| 18090 | 3241 | 2019-09-06 17:24:44 | NaN |
| 18091 | 3241 | 2019-09-06 17:30:05 | NaN |
Размер набора данных: (18092, 3) Количество элементов данных: 54276 Количество дубликатов в наименованиях признаков: 0 Уникальные наименования признаков: ['key', 'Время замера', 'Температура'] Количество пропущенных значений: 3427 Процент пропущенных значений: 6.3 % Типы данных набора данных:
int64 1 object 1 float64 1 dtype: int64
show_na(data_temp)
| Всего пропусков | % | |
|---|---|---|
| Температура | 3427 | 18.9 |
| key | 0 | 0.0 |
| Время замера | 0 | 0.0 |
pic_na(data_temp)
Данные о подаче сыпучих материалов (объём)
key, Время замера.Температура и составляют почти 20 % от всех значений признака.Промежуточный вывод
key — номер партии. Признак не содержит пропущенные значения. Может являться ключом, связывающим все наборы данных.Bulk 12, Bulk 14, Bulk 15 и проволочный материал Wire 1. Остальные материалы используются менее часто, а некоторые совсем редко.Производство стали является периодическим. Поэтому продукт сталелитейного производства выходит партиями.
key — номер партии
Признак является категориальным, порядковым.
Шкала измерения признака: порядковая шкала.
Легирующие элементы могут быть введены в состав стали с помощью специальных сплавов или отдельных химических соединений. В ковш-печь легирующие добавки подаются с помощью специальных устройств, таких как трайб-аппараты или бункерные системы.
Подача сыпучих материалов может осуществляться из расходных бункеров сталелитейного цеха. Эти системы обеспечивают непрерывную подачу сыпучих материалов с заданной производительностью.
Bulk N — сыпучий материал номер N
Вносимая масса сыпучего материала (кг)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
Время внесения сыпучего материала (отметка времени с указанием даты)
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
Трайб-аппарат — это специальное устройство, предназначенное для ввода проволоки в расплав металла. Трайб-аппарат подаёт проволоку в расплав стали с определённой скоростью. Скорость подачи проволоки может регулироваться в зависимости от требуемых параметров процесса.
Wire N — проволочный материал номер N
Вносимая масса проволочного материала (кг)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
Время внесения проволочного материала (отметка времени с указанием даты)
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
Продувка расплава стали инертным газом позволяет достичь более равномерного распределения легирующих добавок и усреднения химического состава стали.
Газ 1 — объём продуваемого через расплав инертного газа (м$^3$)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
Продувка инертным газом сопровождается снижением температуры металла, так как газ нагревается и интенсивно уносит тепло. Подогревают расплав стали графитированными электродами.
Графитированные электроды являются токоведущими элементами и обеспечивают передачу электрического тока в расплав стали. Они размещаются таким образом, чтобы они находились над расплавленной сталью. Подача электрического тока через графитированные электроды создаёт дугу, которая и нагревает расплав.
Активная мощность графитированных электродов определяет электрическую энергию, которая преобразуется в тепло и используется для нагревания расплава стали.
Активная мощность — мощность, которая выделяется в дуге (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
Реактивная мощность не участвует в процессе плавки металла и является нежелательным эффектом, так как приводит к потерям энергии.
Реактивная мощность — мощность, которая возвращается обратно в сеть (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
Вместе со значениями активной и реактивной мощности в системе регистрируются время начала и время окончания подачи напряжения на электроды.
Начало нагрева дугой — отметка времени старта подачи напряжения на электроды
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
Конец нагрева дугой — отметка времени прекращения подачи напряжения на электроды
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
Перед введением каждой легирующей добавки измеряют температуру расплава. Перед непосредственным введением добавки через расплав пропускают электрический ток, тем самым нагревая его. Потом добавляют легирующий материал и продувают сплав инертным газом. Повторяют эту последовательность действий для каждой вводимой добавки. По окончании процесса легирования измеряют температуру получившегося сплава.
Температура — температура расплава ($^{\circ}$C)
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
Конечная температура сплава — целевой признак
Температуру регистрируют с одновременной регистрацией времени измерения.
Время замера — отметка времени регистрации температуры расплава
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
Хронометрические данные собраны от различных средств измерения. Их показания не синхронизированы. Возможны расхождения в показаниях.
def descriptive_statistics(values, label):
'''
Описательная статистика переменной, измеряемой в количественной шкале.
Принимает значения признака и название признака.
Возвращает DataFrame с набором статистик.
'''
df = pd.DataFrame([
values.count(),
len(values.unique()),
values.min(),
values.median() - 1.5 * (values.quantile(q=.75) -
values.quantile(q=.25)),
values.quantile(q=.25).round(2),
(values.mode()).to_list(),
values.median().round(2),
values.mean().round(2),
values.quantile(q=.75).round(2),
values.median() + 1.5 * (values.quantile(q=.75) -
values.quantile(q=.25)),
values.max(),
values.max() - values.min(),
values.quantile(q=.75) - values.quantile(q=.25)
],
index=['кол-во значений', 'кол-во уникальных', 'мин.',
'-1.5IQR', '25 %', 'мода', 'медиана',
'среднее ариф.', '75 %', '+1.5IQR', 'макс.',
'размах', 'межквартильный размах'],
columns=[label])
return df
def graph(data, title, xlabel):
'''
Функция строит диаграмму распределения значений и диаграмму размаха
исследуемых данных.
Принимает набор исследуемых данных,
название признака для заголовка графика,
подпись оси Ox.
'''
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 6))
ax1.set_title('Диаграмма распределения и диаграмма размаха' +
f'\nзначений {title}')
ax1.hist(data, bins=100)
ax1.tick_params(labelbottom=False)
ax1.set_ylabel('Частота')
ax2.boxplot(data, vert=False)
ax2.tick_params(left=False, labelleft=False)
ax2.set_xlabel(f'{xlabel}')
plt.show()
def lot(data):
'''
Функция описывает номера партий.
Принимает набор исследуемх данных.
Возвращает датафрейм с характеристиками распределения значений партий.
'''
missing_key = []
for i in range(data['key'].unique().min(),
data['key'].unique().max()+1):
if i not in data['key'].unique():
missing_key.append(i)
return pd.DataFrame({
'кол-во значений': data.shape[0],
'кол-во уникальных': len(data['key'].unique()),
'мин. значение': data['key'].min(),
'макс. значение': data['key'].max(),
'кол-во пропущенных': len(missing_key),
'пропущенные партии': str(missing_key)
}, index=['Номер партии']).T
def time(data, label):
'''
Функция описывает временной признак (секунды).
Принимает набор исследуемых данных и название признака.
Возвращает датафрейм с характеристиками распределения временных значений.
'''
return pd.DataFrame({
'кол-во значений': data.shape[0],
'кол-во уникальных': len(data.unique()),
'первая запись': data.min(),
'последняя запись': data.max()
}, index=[label]).T
def day(data, label):
'''
Функция описывает временной признак (дни).
Принимает набор исследуемых данных и название признака.
Возвращает датафрейм с характеристиками распределения временных значений.
'''
data = pd.to_datetime(data)
stat = pd.DataFrame(pd.to_datetime(data).dt.date.describe()).rename(
columns={pd.DataFrame(data).columns[0]: label},
index={'count': 'кол-во значений',
'unique': 'кол-во уникальных',
'top': 'мода',
'freq': 'частота моды'}).T
stat.loc[label, 'мода'] = stat.loc[label, 'мода'].strftime('%d.%m.%Y')
stat['мин'] = data.min().strftime('%d.%m.%Y')
stat['медиана'] = data.quantile(q=.5).strftime('%d.%m.%Y')
stat['макс'] = data.max().strftime('%d.%m.%Y')
stat['размах'] = (data.max() - data.min()).days + 1
stat['межквартильный размах'] = (data.quantile(q=.75) -
data.quantile(q=.25)).days
return stat.T
lot(data_arc)
| Номер партии | |
|---|---|
| кол-во значений | 14876 |
| кол-во уникальных | 3214 |
| мин. значение | 1 |
| макс. значение | 3241 |
| кол-во пропущенных | 27 |
| пропущенные партии | [41, 42, 195, 279, 355, 382, 506, 529, 540, 60... |
descriptive_statistics(data_arc['Активная мощность'],
'Активная мощность, МВт')
| Активная мощность, МВт | |
|---|---|
| кол-во значений | 14876 |
| кол-во уникальных | 13846 |
| мин. | 0.22312 |
| -1.5IQR | 0.055154 |
| 25 % | 0.47 |
| мода | [0.509728, 0.712905] |
| медиана | 0.6 |
| среднее ариф. | 0.66 |
| 75 % | 0.83 |
| +1.5IQR | 1.144019 |
| макс. | 1.463773 |
| размах | 1.240653 |
| межквартильный размах | 0.362955 |
graph(data_arc['Активная мощность'],
'активной мощности', 'Активная мощность, МВт')
descriptive_statistics(data_arc['Реактивная мощность'],
'Реактивная мощность, МВт')
| Реактивная мощность, МВт | |
|---|---|
| кол-во значений | 14876 |
| кол-во уникальных | 14707 |
| мин. | -715.479924 |
| -1.5IQR | 0.035101 |
| 25 % | 0.34 |
| мода | [0.257418, 0.310365] |
| медиана | 0.44 |
| среднее ариф. | 0.44 |
| 75 % | 0.61 |
| +1.5IQR | 0.848178 |
| макс. | 1.270284 |
| размах | 716.750208 |
| межквартильный размах | 0.271026 |
graph(data_arc['Реактивная мощность'],
'реактивной мощности', 'Реактивная мощность, МВт')
Посмотрим на значения, физически достижимые на практике: положительные значения реактивной мощности.
descriptive_statistics(data_arc.loc[data_arc['Реактивная мощность'] > 0,
'Реактивная мощность'],
'Реактивная мощность, МВт')
| Реактивная мощность, МВт | |
|---|---|
| кол-во значений | 14875 |
| кол-во уникальных | 14706 |
| мин. | 0.153777 |
| -1.5IQR | 0.035115 |
| 25 % | 0.34 |
| мода | [0.257418, 0.310365] |
| медиана | 0.44 |
| среднее ариф. | 0.49 |
| 75 % | 0.61 |
| +1.5IQR | 0.848215 |
| макс. | 1.270284 |
| размах | 1.116507 |
| межквартильный размах | 0.271033 |
graph(data_arc.loc[data_arc['Реактивная мощность'] > 0, 'Реактивная мощность'],
'реактивной мощности', 'Реактивная мощность, МВт')
time(data_arc.loc[data_arc['Начало нагрева дугой'].notna(),
'Начало нагрева дугой'], 'Начало нагрева дугой')
| Начало нагрева дугой | |
|---|---|
| кол-во значений | 14876 |
| кол-во уникальных | 14876 |
| первая запись | 2019-05-03 11:02:14 |
| последняя запись | 2019-09-06 17:24:54 |
day(data_arc.loc[data_arc['Начало нагрева дугой'].notna(),
'Начало нагрева дугой'], 'Начало нагрева дугой')
| Начало нагрева дугой | |
|---|---|
| кол-во значений | 14876 |
| кол-во уникальных | 123 |
| мода | 06.06.2019 |
| частота моды | 167 |
| мин | 03.05.2019 |
| медиана | 03.07.2019 |
| макс | 06.09.2019 |
| размах | 127 |
| межквартильный размах | 64 |
time(data_arc.loc[data_arc['Конец нагрева дугой'].notna(),
'Конец нагрева дугой'], 'Конец нагрева дугой')
| Конец нагрева дугой | |
|---|---|
| кол-во значений | 14876 |
| кол-во уникальных | 14876 |
| первая запись | 2019-05-03 11:06:02 |
| последняя запись | 2019-09-06 17:26:15 |
day(data_arc.loc[data_arc['Конец нагрева дугой'].notna(),
'Конец нагрева дугой'], 'Конец нагрева дугой')
| Конец нагрева дугой | |
|---|---|
| кол-во значений | 14876 |
| кол-во уникальных | 123 |
| мода | 06.06.2019 |
| частота моды | 168 |
| мин | 03.05.2019 |
| медиана | 03.07.2019 |
| макс | 06.09.2019 |
| размах | 127 |
| межквартильный размах | 64 |
lot(data_bulk)
| Номер партии | |
|---|---|
| кол-во значений | 3129 |
| кол-во уникальных | 3129 |
| мин. значение | 1 |
| макс. значение | 3241 |
| кол-во пропущенных | 112 |
| пропущенные партии | [41, 42, 51, 52, 53, 54, 55, 56, 72, 80, 81, 1... |
lot(data_bulk_time)
| Номер партии | |
|---|---|
| кол-во значений | 3129 |
| кол-во уникальных | 3129 |
| мин. значение | 1 |
| макс. значение | 3241 |
| кол-во пропущенных | 112 |
| пропущенные партии | [41, 42, 51, 52, 53, 54, 55, 56, 72, 80, 81, 1... |
df = pd.DataFrame()
for i in range(1, 16):
df = df.join(
descriptive_statistics(
data_bulk.loc[data_bulk[f'Bulk {i}'].notna(), f'Bulk {i}'],
f'{i}'),
how='right').rename_axis('Сыпучий материал', axis=1)
df
| Сыпучий материал | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| кол-во значений | 252 | 22 | 1298 | 1014 | 77 | 576 | 25 | 1 | 19 | 176 | 177 | 2450 | 18 | 2806 | 2248 |
| кол-во уникальных | 47 | 15 | 278 | 206 | 55 | 205 | 25 | 1 | 10 | 77 | 101 | 331 | 14 | 284 | 156 |
| мин. | 10.0 | 228.0 | 6.0 | 12.0 | 11.0 | 17.0 | 47.0 | 49.0 | 63.0 | 24.0 | 8.0 | 53.0 | 151.0 | 16.0 | 1.0 |
| -1.5IQR | 2.5 | 227.875 | -43.5 | 10.5 | -7.0 | -30.875 | -78.5 | 49.0 | 61.25 | 29.5 | -57.5 | 40.0 | 80.125 | 20.875 | 10.0 |
| 25 % | 27.0 | 242.0 | 58.0 | 72.0 | 70.0 | 69.75 | 155.0 | 49.0 | 66.0 | 64.0 | 25.0 | 204.0 | 153.25 | 119.0 | 105.0 |
| мода | [27.0] | [254.0] | [21.0] | [88.0, 116.0] | [74.0] | [76.0] | [47.0, 50.0, 54.0, 75.0, 92.0, 108.0, 155.0, 1... | [49.0] | [66.0, 68.0] | [105.0] | [18.0] | [206.0] | [153.0, 154.0] | [102.0] | [104.0] |
| медиана | 31.0 | 251.5 | 97.5 | 102.0 | 86.0 | 100.0 | 298.0 | 49.0 | 68.0 | 86.5 | 64.0 | 208.0 | 155.5 | 151.0 | 160.0 |
| среднее ариф. | 39.24 | 253.05 | 113.88 | 104.39 | 107.03 | 118.93 | 305.6 | 49.0 | 76.32 | 83.28 | 76.82 | 260.47 | 181.11 | 170.28 | 160.51 |
| 75 % | 46.0 | 257.75 | 152.0 | 133.0 | 132.0 | 157.0 | 406.0 | 49.0 | 70.5 | 102.0 | 106.0 | 316.0 | 203.5 | 205.75 | 205.0 |
| +1.5IQR | 59.5 | 275.125 | 238.5 | 193.5 | 179.0 | 230.875 | 674.5 | 49.0 | 74.75 | 143.5 | 185.5 | 376.0 | 230.875 | 281.125 | 310.0 |
| макс. | 185.0 | 325.0 | 454.0 | 281.0 | 603.0 | 503.0 | 772.0 | 49.0 | 147.0 | 159.0 | 313.0 | 1849.0 | 305.0 | 636.0 | 405.0 |
| размах | 175.0 | 97.0 | 448.0 | 269.0 | 592.0 | 486.0 | 725.0 | 0.0 | 84.0 | 135.0 | 305.0 | 1796.0 | 154.0 | 620.0 | 404.0 |
| межквартильный размах | 19.0 | 15.75 | 94.0 | 61.0 | 62.0 | 87.25 | 251.0 | 0.0 | 4.5 | 38.0 | 81.0 | 112.0 | 50.25 | 86.75 | 100.0 |
for i in range(1, 16):
graph(data_bulk.loc[data_bulk[f'Bulk {i}'].notna(), f'Bulk {i}'],
f'массы сыпучего материала номер {i}',
f'Масса сыпучего материала номер {i}, кг')
Bulk 1 — масса сыпучего материала номер 1
Bulk 2 — масса сыпучего материала номер 2
Bulk 3 — масса сыпучего материала номер 3
Bulk 4 — масса сыпучего материала номер 4
Bulk 5 — масса сыпучего материала номер 5
Bulk 6 — масса сыпучего материала номер 6
Bulk 7 — масса сыпучего материала номер 7
Bulk 8 — масса сыпучего материала номер 8
Bulk 9 — масса сыпучего материала номер 9
Bulk 10 — масса сыпучего материала номер 10
Bulk 11 — масса сыпучего материала номер 11
Bulk 12 — масса сыпучего материала номер 12
Bulk 13 — масса сыпучего материала номер 13
Bulk 14 — масса сыпучего материала номер 14
Bulk 15 — масса сыпучего материала номер 15
df = pd.DataFrame()
for i in range(1, 16):
df = df.join(
time(data_bulk_time.loc[data_bulk_time[f'Bulk {i}'].notna(),
f'Bulk {i}'], f'{i}'),
how='right').rename_axis('Сыпучий материал', axis=0)
df.T
| Сыпучий материал | кол-во значений | кол-во уникальных | первая запись | последняя запись |
|---|---|---|---|---|
| 1 | 252 | 252 | 2019-05-03 17:42:46 | 2019-09-05 09:11:32 |
| 2 | 22 | 22 | 2019-05-07 15:39:35 | 2019-08-13 11:47:39 |
| 3 | 1298 | 1298 | 2019-05-03 20:40:25 | 2019-09-06 12:26:52 |
| 4 | 1014 | 1014 | 2019-05-03 11:28:48 | 2019-09-05 03:35:21 |
| 5 | 77 | 77 | 2019-05-07 15:19:17 | 2019-09-02 18:16:52 |
| 6 | 576 | 576 | 2019-05-03 19:09:15 | 2019-09-06 16:24:28 |
| 7 | 25 | 25 | 2019-05-07 18:11:01 | 2019-09-05 19:07:49 |
| 8 | 1 | 1 | 2019-07-08 17:14:53 | 2019-07-08 17:14:53 |
| 9 | 19 | 19 | 2019-05-14 11:57:58 | 2019-08-16 09:11:56 |
| 10 | 176 | 176 | 2019-05-06 07:54:02 | 2019-09-04 10:03:22 |
| 11 | 177 | 177 | 2019-05-05 23:43:24 | 2019-09-06 05:03:14 |
| 12 | 2450 | 2450 | 2019-05-03 11:24:31 | 2019-09-06 15:01:44 |
| 13 | 18 | 18 | 2019-05-05 02:10:21 | 2019-09-01 01:53:02 |
| 14 | 2806 | 2806 | 2019-05-03 11:14:50 | 2019-09-06 17:26:33 |
| 15 | 2248 | 2248 | 2019-05-03 11:10:43 | 2019-09-06 17:23:15 |
df = pd.DataFrame()
for i in range(1, 16):
df = df.join(
day(data_bulk_time.loc[data_bulk_time[f'Bulk {i}'].notna(),
f'Bulk {i}'], f'{i}'),
how='right').rename_axis('Сыпучий материал', axis=0)
df.T
| Сыпучий материал | кол-во значений | кол-во уникальных | мода | частота моды | мин | медиана | макс | размах | межквартильный размах |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 252 | 91 | 06.07.2019 | 9 | 03.05.2019 | 25.06.2019 | 05.09.2019 | 125 | 62 |
| 2 | 22 | 5 | 27.07.2019 | 7 | 07.05.2019 | 27.07.2019 | 13.08.2019 | 98 | 76 |
| 3 | 1298 | 120 | 06.06.2019 | 27 | 03.05.2019 | 04.07.2019 | 06.09.2019 | 126 | 63 |
| 4 | 1014 | 117 | 19.06.2019 | 24 | 03.05.2019 | 28.06.2019 | 05.09.2019 | 125 | 65 |
| 5 | 77 | 22 | 02.09.2019 | 9 | 07.05.2019 | 25.07.2019 | 02.09.2019 | 119 | 54 |
| 6 | 576 | 104 | 24.07.2019 | 21 | 03.05.2019 | 09.07.2019 | 06.09.2019 | 126 | 61 |
| 7 | 25 | 9 | 27.07.2019 | 7 | 07.05.2019 | 27.07.2019 | 05.09.2019 | 122 | 23 |
| 8 | 1 | 1 | 08.07.2019 | 1 | 08.07.2019 | 08.07.2019 | 08.07.2019 | 1 | 0 |
| 9 | 19 | 4 | 14.05.2019 | 10 | 14.05.2019 | 14.05.2019 | 16.08.2019 | 94 | 93 |
| 10 | 176 | 53 | 21.05.2019 | 10 | 06.05.2019 | 06.07.2019 | 04.09.2019 | 122 | 62 |
| 11 | 177 | 72 | 24.07.2019 | 12 | 05.05.2019 | 24.07.2019 | 06.09.2019 | 124 | 57 |
| 12 | 2450 | 123 | 01.09.2019 | 31 | 03.05.2019 | 03.07.2019 | 06.09.2019 | 127 | 66 |
| 13 | 18 | 17 | 11.05.2019 | 2 | 05.05.2019 | 01.07.2019 | 01.09.2019 | 119 | 67 |
| 14 | 2806 | 123 | 06.07.2019 | 32 | 03.05.2019 | 03.07.2019 | 06.09.2019 | 127 | 65 |
| 15 | 2248 | 123 | 01.09.2019 | 29 | 03.05.2019 | 03.07.2019 | 06.09.2019 | 127 | 65 |
lot(data_wire)
| Номер партии | |
|---|---|
| кол-во значений | 3081 |
| кол-во уникальных | 3081 |
| мин. значение | 1 |
| макс. значение | 3241 |
| кол-во пропущенных | 160 |
| пропущенные партии | [41, 42, 51, 52, 53, 54, 55, 56, 81, 82, 83, 8... |
lot(data_wire_time)
| Номер партии | |
|---|---|
| кол-во значений | 3081 |
| кол-во уникальных | 3081 |
| мин. значение | 1 |
| макс. значение | 3241 |
| кол-во пропущенных | 160 |
| пропущенные партии | [41, 42, 51, 52, 53, 54, 55, 56, 81, 82, 83, 8... |
df = pd.DataFrame()
for i in range(1, 10):
df = df.join(
descriptive_statistics(
data_wire.loc[data_wire[f'Wire {i}'].notna(), f'Wire {i}'],
f'{i}'),
how='right').rename_axis('Проволочный материал', axis=1)
df
| Проволочный материал | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|
| кол-во значений | 3055 | 1079 | 63 | 14 | 1 | 73 | 11 | 19 | 29 |
| кол-во уникальных | 2251 | 713 | 56 | 14 | 1 | 69 | 10 | 13 | 25 |
| мин. | 1.9188 | 0.03016 | 0.144144 | 24.148801 | 15.132 | 0.03432 | 0.234208 | 45.076721 | 4.6228 |
| -1.5IQR | 19.241035 | -34.907861 | -36.480479 | -7.742143 | 15.132 | -16.662361 | 1.332057 | 43.287913 | -2.639004 |
| 25 % | 72.12 | 20.19 | 95.14 | 40.81 | 15.13 | 25.05 | 6.76 | 46.09 | 22.06 |
| мода | [105.0504] | [30.09968] | [0.144144, 93.165077] | [24.148801, 25.132641, 33.182243, 40.069122, 4... | [15.132] | [18.086641, 20.145842, 25.0536, 38.198162] | [12.354473] | [46.187439000000005] | [30.066399] |
| медиана | 100.16 | 40.14 | 235.19 | 45.23 | 15.13 | 42.08 | 9.02 | 46.28 | 30.07 |
| среднее ариф. | 100.9 | 50.58 | 189.48 | 57.44 | 15.13 | 48.02 | 10.04 | 53.63 | 34.16 |
| 75 % | 126.06 | 70.23 | 276.25 | 76.12 | 15.13 | 64.21 | 11.89 | 48.09 | 43.86 |
| +1.5IQR | 181.075433 | 115.193773 | 506.870433 | 98.210708 | 15.132 | 100.815009 | 16.70196 | 49.272085 | 62.771802 |
| макс. | 330.314424 | 282.780152 | 385.008668 | 113.231044 | 15.132 | 180.454575 | 32.847674 | 102.762401 | 90.053604 |
| размах | 328.395624 | 282.749992 | 384.864524 | 89.082243 | 0.0 | 180.420255 | 32.613466 | 57.68568 | 85.430804 |
| межквартильный размах | 53.944799 | 50.033878 | 181.11697 | 35.317617 | 0.0 | 39.159123 | 5.123301 | 1.994724 | 21.803602 |
for i in range(1, 10):
graph(data_wire.loc[data_wire[f'Wire {i}'].notna(), f'Wire {i}'],
f'массы проволочного материала номер {i}',
f'Масса проволочного материала номер {i}, кг')
Wire 1 — масса проволочного материала номер 1
Wire 2 — масса проволочного материала номер 2
Wire 3 — масса проволочного материала номер 3
Wire 4 — масса проволочного материала номер 4
Wire 5 — масса проволочного материала номер 5
Wire 6 — масса проволочного материала номер 6
Wire 7 — масса проволочного материала номер 7
Wire 8 — масса проволочного материала номер 8
Wire 9 — масса проволочного материала номер 9
df = pd.DataFrame()
for i in range(1, 10):
df = df.join(
time(data_wire_time.loc[data_wire_time[f'Wire {i}'].notna(),
f'Wire {i}'], f'{i}'),
how='right').rename_axis('Проволочный материал', axis=0)
df.T
| Проволочный материал | кол-во значений | кол-во уникальных | первая запись | последняя запись |
|---|---|---|---|---|
| 1 | 3055 | 3055 | 2019-05-03 11:06:19 | 2019-09-06 17:10:06 |
| 2 | 1079 | 1079 | 2019-05-03 13:15:34 | 2019-09-06 07:35:40 |
| 3 | 63 | 63 | 2019-05-04 04:34:27 | 2019-09-02 07:14:44 |
| 4 | 14 | 14 | 2019-05-07 15:19:17 | 2019-08-13 03:16:45 |
| 5 | 1 | 1 | 2019-08-13 06:14:30 | 2019-08-13 06:14:30 |
| 6 | 73 | 73 | 2019-05-07 14:46:05 | 2019-08-18 19:10:56 |
| 7 | 11 | 11 | 2019-07-27 05:49:05 | 2019-08-13 10:25:22 |
| 8 | 19 | 19 | 2019-05-14 11:29:24 | 2019-08-16 08:56:23 |
| 9 | 29 | 29 | 2019-05-04 17:21:27 | 2019-09-03 12:55:23 |
df = pd.DataFrame()
for i in range(1, 10):
df = df.join(
day(data_wire_time.loc[data_wire_time[f'Wire {i}'].notna(),
f'Wire {i}'], f'{i}'),
how='right').rename_axis('Проволочный материал', axis=0)
df.T
| Проволочный материал | кол-во значений | кол-во уникальных | мода | частота моды | мин | медиана | макс | размах | межквартильный размах |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 3055 | 123 | 06.07.2019 | 35 | 03.05.2019 | 03.07.2019 | 06.09.2019 | 127 | 64 |
| 2 | 1079 | 116 | 11.08.2019 | 23 | 03.05.2019 | 04.07.2019 | 06.09.2019 | 126 | 64 |
| 3 | 63 | 22 | 27.07.2019 | 7 | 04.05.2019 | 21.07.2019 | 02.09.2019 | 122 | 62 |
| 4 | 14 | 5 | 27.07.2019 | 7 | 07.05.2019 | 27.07.2019 | 13.08.2019 | 98 | 6 |
| 5 | 1 | 1 | 13.08.2019 | 1 | 13.08.2019 | 13.08.2019 | 13.08.2019 | 1 | 0 |
| 6 | 73 | 11 | 08.05.2019 | 16 | 07.05.2019 | 28.07.2019 | 18.08.2019 | 104 | 96 |
| 7 | 11 | 3 | 27.07.2019 | 4 | 27.07.2019 | 12.08.2019 | 13.08.2019 | 18 | 16 |
| 8 | 19 | 4 | 14.05.2019 | 10 | 14.05.2019 | 14.05.2019 | 16.08.2019 | 94 | 93 |
| 9 | 29 | 8 | 09.08.2019 | 8 | 04.05.2019 | 11.06.2019 | 03.09.2019 | 122 | 60 |
lot(data_gas)
| Номер партии | |
|---|---|
| кол-во значений | 3239 |
| кол-во уникальных | 3239 |
| мин. значение | 1 |
| макс. значение | 3241 |
| кол-во пропущенных | 2 |
| пропущенные партии | [193, 259] |
descriptive_statistics(data_gas['Газ 1'], 'Объём подаваемого газа, м$^3$')
| Объём подаваемого газа, м$^3$ | |
|---|---|
| кол-во значений | 3239 |
| кол-во уникальных | 3239 |
| мин. | 0.008399 |
| -1.5IQR | -0.253973 |
| 25 % | 7.04 |
| мода | [0.0083985291, 0.0166956024, 0.2630289536, 0.2... |
| медиана | 9.84 |
| среднее ариф. | 11.0 |
| 75 % | 13.77 |
| +1.5IQR | 19.926507 |
| макс. | 77.99504 |
| размах | 77.986641 |
| межквартильный размах | 6.726827 |
graph(data_gas['Газ 1'],
'объёма подаваемого газа', 'Объём подаваемого газа, м$^3$')
lot(data_temp)
| Номер партии | |
|---|---|
| кол-во значений | 18092 |
| кол-во уникальных | 3216 |
| мин. значение | 1 |
| макс. значение | 3241 |
| кол-во пропущенных | 25 |
| пропущенные партии | [41, 42, 355, 382, 506, 529, 540, 607, 683, 71... |
descriptive_statistics(data_temp['Температура'], 'Температура, $^{\circ}$C')
| Температура, $^{\circ}$C | |
|---|---|
| кол-во значений | 14665 |
| кол-во уникальных | 173 |
| мин. | 1191.0 |
| -1.5IQR | 1561.5 |
| 25 % | 1580.0 |
| мода | [1593.0] |
| медиана | 1590.0 |
| среднее ариф. | 1590.72 |
| 75 % | 1599.0 |
| +1.5IQR | 1618.5 |
| макс. | 1705.0 |
| размах | 514.0 |
| межквартильный размах | 19.0 |
graph(data_temp.loc[data_temp['Температура'].notna(), 'Температура'],
'температуры', 'Температура, $^{\circ}$C')
time(data_temp['Время замера'], 'Время замера')
| Время замера | |
|---|---|
| кол-во значений | 18092 |
| кол-во уникальных | 18092 |
| первая запись | 2019-05-03 11:02:04 |
| последняя запись | 2019-09-06 17:30:05 |
day(data_temp['Время замера'], 'Время замера')
| Время замера | |
|---|---|
| кол-во значений | 18092 |
| кол-во уникальных | 123 |
| мода | 06.06.2019 |
| частота моды | 201 |
| мин | 03.05.2019 |
| медиана | 03.07.2019 |
| макс | 06.09.2019 |
| размах | 127 |
| межквартильный размах | 64 |
Промежуточный вывод
Партии, для которых наблюдаются аномальные значения температуры (менее 1300 $^{\circ}$C):
data_temp.loc[data_temp['Температура'] < 1300, 'key'].tolist()
[867, 1214, 1619, 2052, 2561]
data_temp.shape
(18092, 3)
Удалим из набора данных о результатах измерения температуры сведения о партиях с аномальными значениями температуры.
for key in data_temp.loc[data_temp['Температура'] < 1300, 'key'].tolist():
data_temp = data_temp.loc[~(data_temp['key'] == key)]
len(data_temp.loc[data_temp['Температура'] < 1300])
0
data_temp.shape
(18065, 3)
Партии, для которых наблюдаются аномальные (неположительные) значения реактивной мощности:
data_arc.loc[data_arc['Реактивная мощность'] <= 0, 'key'].tolist()
[2116]
data_arc.shape
(14876, 5)
Удалим из набора данных о параметрах работы электродов сведения о партиях с аномальными значениями реактивной мощности.
for key in data_arc.loc[data_arc['Реактивная мощность'] <= 0, 'key'].tolist():
data_arc = data_arc.loc[~(data_arc['key'] == key)]
len(data_arc.loc[data_arc['Реактивная мощность'] <= 0])
0
data_arc.shape
(14872, 5)
Рассчитаем для каждой подачи напряжения на электроды значение полной мощности по формуле:
$Полная\ мощность = \sqrt{(Активная\ мощность)^2 + (Реактивная\ мощность)^2}$
data_arc['full_power'] = (data_arc['Активная мощность'] ** 2 +
data_arc['Реактивная мощность'] ** 2) ** 0.5
data_arc.head()
| key | Начало нагрева дугой | Конец нагрева дугой | Активная мощность | Реактивная мощность | full_power | |
|---|---|---|---|---|---|---|
| 0 | 1 | 2019-05-03 11:02:14 | 2019-05-03 11:06:02 | 0.305130 | 0.211253 | 0.371123 |
| 1 | 1 | 2019-05-03 11:07:28 | 2019-05-03 11:10:33 | 0.765658 | 0.477438 | 0.902319 |
| 2 | 1 | 2019-05-03 11:11:44 | 2019-05-03 11:14:36 | 0.580313 | 0.430460 | 0.722536 |
| 3 | 1 | 2019-05-03 11:18:14 | 2019-05-03 11:24:19 | 0.518496 | 0.379979 | 0.642824 |
| 4 | 1 | 2019-05-03 11:26:09 | 2019-05-03 11:28:37 | 0.867133 | 0.643691 | 1.079934 |
Рассчитаем для каждой подачи напряжения на электроды значение коэффициента мощности по формуле:
$Коэффициент\ мощности = \frac{Активная\ мощность}{Полная\ мощность}$
data_arc['power_factor'] = data_arc['Активная мощность'] / data_arc['full_power']
data_arc.head()
| key | Начало нагрева дугой | Конец нагрева дугой | Активная мощность | Реактивная мощность | full_power | power_factor | |
|---|---|---|---|---|---|---|---|
| 0 | 1 | 2019-05-03 11:02:14 | 2019-05-03 11:06:02 | 0.305130 | 0.211253 | 0.371123 | 0.822181 |
| 1 | 1 | 2019-05-03 11:07:28 | 2019-05-03 11:10:33 | 0.765658 | 0.477438 | 0.902319 | 0.848545 |
| 2 | 1 | 2019-05-03 11:11:44 | 2019-05-03 11:14:36 | 0.580313 | 0.430460 | 0.722536 | 0.803161 |
| 3 | 1 | 2019-05-03 11:18:14 | 2019-05-03 11:24:19 | 0.518496 | 0.379979 | 0.642824 | 0.806591 |
| 4 | 1 | 2019-05-03 11:26:09 | 2019-05-03 11:28:37 | 0.867133 | 0.643691 | 1.079934 | 0.802950 |
Рассчитаем время, в течение которого подавалась электроэнергия для подогрева расплава, по формуле:
$Время\ нагрева = Конец\ нагрева\ дугой - Начало\ нагрева\ дугой$
data_arc['heating_time'] = (pd.to_datetime(data_arc['Конец нагрева дугой']) -
pd.to_datetime(data_arc['Начало нагрева дугой'])
).dt.total_seconds()
data_arc.head()
| key | Начало нагрева дугой | Конец нагрева дугой | Активная мощность | Реактивная мощность | full_power | power_factor | heating_time | |
|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2019-05-03 11:02:14 | 2019-05-03 11:06:02 | 0.305130 | 0.211253 | 0.371123 | 0.822181 | 228.0 |
| 1 | 1 | 2019-05-03 11:07:28 | 2019-05-03 11:10:33 | 0.765658 | 0.477438 | 0.902319 | 0.848545 | 185.0 |
| 2 | 1 | 2019-05-03 11:11:44 | 2019-05-03 11:14:36 | 0.580313 | 0.430460 | 0.722536 | 0.803161 | 172.0 |
| 3 | 1 | 2019-05-03 11:18:14 | 2019-05-03 11:24:19 | 0.518496 | 0.379979 | 0.642824 | 0.806591 | 365.0 |
| 4 | 1 | 2019-05-03 11:26:09 | 2019-05-03 11:28:37 | 0.867133 | 0.643691 | 1.079934 | 0.802950 | 148.0 |
Рассчитаем, какое количество энергии (в МДж) потреблялось при каждом нагреве расплава, по формуле:
$Потреблённая\ энергия = Полная\ мощность \times Время\ нагрева$
data_arc['energy'] = data_arc['full_power'] * data_arc['heating_time']
data_arc.head()
| key | Начало нагрева дугой | Конец нагрева дугой | Активная мощность | Реактивная мощность | full_power | power_factor | heating_time | energy | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2019-05-03 11:02:14 | 2019-05-03 11:06:02 | 0.305130 | 0.211253 | 0.371123 | 0.822181 | 228.0 | 84.616003 |
| 1 | 1 | 2019-05-03 11:07:28 | 2019-05-03 11:10:33 | 0.765658 | 0.477438 | 0.902319 | 0.848545 | 185.0 | 166.928978 |
| 2 | 1 | 2019-05-03 11:11:44 | 2019-05-03 11:14:36 | 0.580313 | 0.430460 | 0.722536 | 0.803161 | 172.0 | 124.276277 |
| 3 | 1 | 2019-05-03 11:18:14 | 2019-05-03 11:24:19 | 0.518496 | 0.379979 | 0.642824 | 0.806591 | 365.0 | 234.630603 |
| 4 | 1 | 2019-05-03 11:26:09 | 2019-05-03 11:28:37 | 0.867133 | 0.643691 | 1.079934 | 0.802950 | 148.0 | 159.830252 |
Приведём наименования признаков к "змеиному_регистру".
data_bulk = data_bulk.rename(
columns=lambda column: re.sub(r'(?<!^)(?=[A-Z])| ', '_', column).lower())
data_bulk.columns
Index(['key', 'bulk_1', 'bulk_2', 'bulk_3', 'bulk_4', 'bulk_5', 'bulk_6',
'bulk_7', 'bulk_8', 'bulk_9', 'bulk_10', 'bulk_11', 'bulk_12',
'bulk_13', 'bulk_14', 'bulk_15'],
dtype='object')
data_bulk.shape
(3129, 16)
Рассчитаем для каждой партии, сколько видов сыпучих материалов вносили в расплав.
data_bulk['bulk_sum'] = data_bulk.drop(['key'], axis=1).sum(axis=1)
data_bulk['bulk_count'] = data_bulk.drop(['key', 'bulk_sum'],
axis=1).count(axis=1)
data_bulk.head()
| key | bulk_1 | bulk_2 | bulk_3 | bulk_4 | bulk_5 | bulk_6 | bulk_7 | bulk_8 | bulk_9 | bulk_10 | bulk_11 | bulk_12 | bulk_13 | bulk_14 | bulk_15 | bulk_sum | bulk_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | NaN | NaN | NaN | 43.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 206.0 | NaN | 150.0 | 154.0 | 553.0 | 4 |
| 1 | 2 | NaN | NaN | NaN | 73.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 206.0 | NaN | 149.0 | 154.0 | 582.0 | 4 |
| 2 | 3 | NaN | NaN | NaN | 34.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 205.0 | NaN | 152.0 | 153.0 | 544.0 | 4 |
| 3 | 4 | NaN | NaN | NaN | 81.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 207.0 | NaN | 153.0 | 154.0 | 595.0 | 4 |
| 4 | 5 | NaN | NaN | NaN | 78.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 203.0 | NaN | 151.0 | 152.0 | 584.0 | 4 |
data_bulk.shape
(3129, 18)
Приведём наименования признаков к "змеиному_регистру".
data_wire = data_wire.rename(
columns=lambda column: re.sub(r'(?<!^)(?=[A-Z])| ', '_', column).lower())
data_wire.columns
Index(['key', 'wire_1', 'wire_2', 'wire_3', 'wire_4', 'wire_5', 'wire_6',
'wire_7', 'wire_8', 'wire_9'],
dtype='object')
data_wire.shape
(3081, 10)
Рассчитаем для каждой партии, сколько видов проволочных материалов вносили в расплав.
data_wire['wire_sum'] = data_wire.drop(['key'], axis=1).sum(axis=1)
data_wire['wire_count'] = data_wire.drop(['key', 'wire_sum'],
axis=1).count(axis=1)
data_wire.head()
| key | wire_1 | wire_2 | wire_3 | wire_4 | wire_5 | wire_6 | wire_7 | wire_8 | wire_9 | wire_sum | wire_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 60.059998 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 60.059998 | 1 |
| 1 | 2 | 96.052315 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 96.052315 | 1 |
| 2 | 3 | 91.160157 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 91.160157 | 1 |
| 3 | 4 | 89.063515 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 89.063515 | 1 |
| 4 | 5 | 89.238236 | 9.11456 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 98.352796 | 2 |
data_bulk.shape
(3129, 18)
Количество партий, для которых неизвестны некоторые результаты измерения температуры:
len(data_temp.loc[data_temp['Температура'].isna(), 'key'].unique())
738
data_temp.shape
(18065, 3)
Поскольку отсутствующие значения температуры могут свидетельствовать о неисправности средства измерения и, кроме того, последняя измеренная температура является целевым признаком, необходимо удалить недостаточно достоверные сведения о таких партиях.
for key in data_temp.loc[data_temp['Температура'].isna(), 'key'].unique():
data_temp = data_temp.loc[~(data_temp['key'] == key)]
len(data_temp.loc[data_temp['Температура'].isna(), 'key'].unique())
0
data_temp.shape
(13905, 3)
Среди значений массы сыпучих материалов присутствуют пропуски, причиной которых является технологический процесс стадии легирования: не все сыпучие материалы используются для получения разных марок стали. Каждая марка стали требует своего набора добавок.
data_bulk.head()
| key | bulk_1 | bulk_2 | bulk_3 | bulk_4 | bulk_5 | bulk_6 | bulk_7 | bulk_8 | bulk_9 | bulk_10 | bulk_11 | bulk_12 | bulk_13 | bulk_14 | bulk_15 | bulk_sum | bulk_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | NaN | NaN | NaN | 43.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 206.0 | NaN | 150.0 | 154.0 | 553.0 | 4 |
| 1 | 2 | NaN | NaN | NaN | 73.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 206.0 | NaN | 149.0 | 154.0 | 582.0 | 4 |
| 2 | 3 | NaN | NaN | NaN | 34.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 205.0 | NaN | 152.0 | 153.0 | 544.0 | 4 |
| 3 | 4 | NaN | NaN | NaN | 81.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 207.0 | NaN | 153.0 | 154.0 | 595.0 | 4 |
| 4 | 5 | NaN | NaN | NaN | 78.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 203.0 | NaN | 151.0 | 152.0 | 584.0 | 4 |
data_bulk.isna().sum().sum()
35776
Можно с уверенностью утверждать, что пропущенные значения необходимо заполнить нулём, поскольку компоненты с пропусками при производстве каждой партии в расплав не добавлялись.
data_bulk.fillna(0, inplace=True)
data_bulk.head()
| key | bulk_1 | bulk_2 | bulk_3 | bulk_4 | bulk_5 | bulk_6 | bulk_7 | bulk_8 | bulk_9 | bulk_10 | bulk_11 | bulk_12 | bulk_13 | bulk_14 | bulk_15 | bulk_sum | bulk_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0.0 | 0.0 | 0.0 | 43.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 206.0 | 0.0 | 150.0 | 154.0 | 553.0 | 4 |
| 1 | 2 | 0.0 | 0.0 | 0.0 | 73.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 206.0 | 0.0 | 149.0 | 154.0 | 582.0 | 4 |
| 2 | 3 | 0.0 | 0.0 | 0.0 | 34.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 205.0 | 0.0 | 152.0 | 153.0 | 544.0 | 4 |
| 3 | 4 | 0.0 | 0.0 | 0.0 | 81.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 207.0 | 0.0 | 153.0 | 154.0 | 595.0 | 4 |
| 4 | 5 | 0.0 | 0.0 | 0.0 | 78.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 203.0 | 0.0 | 151.0 | 152.0 | 584.0 | 4 |
data_bulk.isna().sum().sum()
0
Среди значений массы проволочных материалов также имеются пропуски. Аналогично, можно утверждать, что их появление связано с особенностями технологического процесса стадии легирования. Для производства каждой марки стали необходимо использовать разный набор проволочных материалов.
data_wire.head()
| key | wire_1 | wire_2 | wire_3 | wire_4 | wire_5 | wire_6 | wire_7 | wire_8 | wire_9 | wire_sum | wire_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 60.059998 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 60.059998 | 1 |
| 1 | 2 | 96.052315 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 96.052315 | 1 |
| 2 | 3 | 91.160157 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 91.160157 | 1 |
| 3 | 4 | 89.063515 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 89.063515 | 1 |
| 4 | 5 | 89.238236 | 9.11456 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 98.352796 | 2 |
data_wire.isna().sum().sum()
23385
Эти пропуски также необходимо заполнить нулём, как и в случае с сыпучими материалами, поскольку имеется высокая уверенность в том, что отсутствующие сведения говорят о неиспользовании материала в процессе легирования.
data_wire.fillna(0, inplace=True)
data_wire.head()
| key | wire_1 | wire_2 | wire_3 | wire_4 | wire_5 | wire_6 | wire_7 | wire_8 | wire_9 | wire_sum | wire_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 60.059998 | 0.00000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 60.059998 | 1 |
| 1 | 2 | 96.052315 | 0.00000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 96.052315 | 1 |
| 2 | 3 | 91.160157 | 0.00000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 91.160157 | 1 |
| 3 | 4 | 89.063515 | 0.00000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 89.063515 | 1 |
| 4 | 5 | 89.238236 | 9.11456 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 98.352796 | 2 |
data_wire.isna().sum().sum()
0
Сведение всех данных будем производить, используя номер партии в качестве ключа для объединения.
Прежде всего сформируем набор данных из номеров партий и конечной температурой расплава — целевой переменной.
data = pd.DataFrame(data_temp.groupby('key')['key'].tail(1)).join(
data_temp.groupby('key')['Температура'].tail(1)).rename(
{'Температура': 'last_temperature'}, axis=1)
data.head()
| key | last_temperature | |
|---|---|---|
| 5 | 1 | 1613.0 |
| 10 | 2 | 1602.0 |
| 16 | 3 | 1599.0 |
| 21 | 4 | 1625.0 |
| 26 | 5 | 1602.0 |
data.shape
(2473, 2)
Теперь добавим к набору данных сведения о начальной температуре легирования.
data = data.merge(
pd.DataFrame(data_temp.groupby('key')['key'].head(1)).join(
data_temp.groupby('key')['Температура'].head(1)).rename(
{'Температура': 'first_temperature'}, axis=1),
on='key')
data.head()
| key | last_temperature | first_temperature | |
|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 |
| 1 | 2 | 1602.0 | 1581.0 |
| 2 | 3 | 1599.0 | 1596.0 |
| 3 | 4 | 1625.0 | 1601.0 |
| 4 | 5 | 1602.0 | 1576.0 |
data.shape
(2473, 3)
Время проведения процесса легирования — это время между первым измерением температуры и последним измерением.
time = pd.DataFrame(data_temp.groupby('key')['key'].tail(1)).join(
pd.to_datetime(data_temp.groupby('key')['Время замера'].tail(1))).rename(
{'Время замера': 'final_time'}, axis=1).merge(
pd.DataFrame(data_temp.groupby('key')['key'].head(1)).join(
pd.to_datetime(data_temp.groupby('key')['Время замера'].head(1))).rename(
{'Время замера': 'initial_time'}, axis=1),
on='key'
)
time.head()
| key | final_time | initial_time | |
|---|---|---|---|
| 0 | 1 | 2019-05-03 11:30:38 | 2019-05-03 11:02:04 |
| 1 | 2 | 2019-05-03 11:55:09 | 2019-05-03 11:34:04 |
| 2 | 3 | 2019-05-03 12:35:57 | 2019-05-03 12:06:44 |
| 3 | 4 | 2019-05-03 12:59:47 | 2019-05-03 12:39:27 |
| 4 | 5 | 2019-05-03 13:36:39 | 2019-05-03 13:11:03 |
time['process_time'] = (pd.to_datetime(time['final_time']) -
pd.to_datetime(time['initial_time'])
).dt.total_seconds()
time.head()
| key | final_time | initial_time | process_time | |
|---|---|---|---|---|
| 0 | 1 | 2019-05-03 11:30:38 | 2019-05-03 11:02:04 | 1714.0 |
| 1 | 2 | 2019-05-03 11:55:09 | 2019-05-03 11:34:04 | 1265.0 |
| 2 | 3 | 2019-05-03 12:35:57 | 2019-05-03 12:06:44 | 1753.0 |
| 3 | 4 | 2019-05-03 12:59:47 | 2019-05-03 12:39:27 | 1220.0 |
| 4 | 5 | 2019-05-03 13:36:39 | 2019-05-03 13:11:03 | 1536.0 |
Добавим сведения о времени проведения процесса легирования к набору данных.
data = data.merge(time[['key', 'process_time']], on='key')
data.head()
| key | last_temperature | first_temperature | process_time | |
|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 |
| 2 | 3 | 1599.0 | 1596.0 | 1753.0 |
| 3 | 4 | 1625.0 | 1601.0 | 1220.0 |
| 4 | 5 | 1602.0 | 1576.0 | 1536.0 |
data.shape
(2473, 4)
Добавим к набору данных сведения о суммарном значении полной мощности. Кроме того, поскольку для каждой партии, в общем случае, производилось несколько операций передачи электродами электроэнергии расплаву, то добавим к набору данных статистические сведения, рассчитанные для каждой партии: среднее арифметическое, минимум и максимум значений.
data = data.merge(
data_arc.groupby('key')['full_power']
.agg(['sum', 'mean', 'min', 'max']).reset_index()
.rename(
{'sum': 'full_power_sum',
'mean': 'full_power_avg',
'min': 'full_power_min',
'max': 'full_power_max'}, axis=1),
on='key')
data.head()
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | |
|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 | 3.718736 | 0.743747 | 0.371123 | 1.079934 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 | 2.588349 | 0.647087 | 0.332731 | 0.955315 |
| 2 | 3 | 1599.0 | 1596.0 | 1753.0 | 5.019223 | 1.003845 | 0.502111 | 1.497189 |
| 3 | 4 | 1625.0 | 1601.0 | 1220.0 | 3.400038 | 0.850010 | 0.393685 | 1.097105 |
| 4 | 5 | 1602.0 | 1576.0 | 1536.0 | 2.816980 | 0.704245 | 0.428064 | 1.110873 |
data.shape
(2470, 8)
Поскольку активная мощность не является аддитивной величиной, то к набору данных можно добавить только статистические показатели: среднее арифметическое, минимум и максимум значений активной мощности.
data = data.merge(
data_arc.groupby('key')['Активная мощность']
.agg(['mean', 'min', 'max']).reset_index()
.rename(
{'mean': 'active_power_avg',
'min': 'active_power_min',
'max': 'active_power_max'}, axis=1),
on='key')
data.head()
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | active_power_avg | active_power_min | active_power_max | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 | 3.718736 | 0.743747 | 0.371123 | 1.079934 | 0.607346 | 0.305130 | 0.867133 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 | 2.588349 | 0.647087 | 0.332731 | 0.955315 | 0.534852 | 0.261665 | 0.786322 |
| 2 | 3 | 1599.0 | 1596.0 | 1753.0 | 5.019223 | 1.003845 | 0.502111 | 1.497189 | 0.812728 | 0.421693 | 1.222963 |
| 3 | 4 | 1625.0 | 1601.0 | 1220.0 | 3.400038 | 0.850010 | 0.393685 | 1.097105 | 0.676622 | 0.310693 | 0.887855 |
| 4 | 5 | 1602.0 | 1576.0 | 1536.0 | 2.816980 | 0.704245 | 0.428064 | 1.110873 | 0.563238 | 0.324563 | 0.892957 |
data.shape
(2470, 11)
Реактивная мощность, также как и активная, не является аддитивной величиной, поэтому и в этом случае к набору данных можно добавить только статистические показатели: среднее арифметическое, минимум и максимум значений реактивной мощности.
data = data.merge(
data_arc.groupby('key')['Реактивная мощность']
.agg(['mean', 'min', 'max']).reset_index()
.rename(
{'mean': 'reactive_power_avg',
'min': 'reactive_power_min',
'max': 'reactive_power_max'}, axis=1),
on='key')
data.head()
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | active_power_avg | active_power_min | active_power_max | reactive_power_avg | reactive_power_min | reactive_power_max | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 | 3.718736 | 0.743747 | 0.371123 | 1.079934 | 0.607346 | 0.305130 | 0.867133 | 0.428564 | 0.211253 | 0.643691 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 | 2.588349 | 0.647087 | 0.332731 | 0.955315 | 0.534852 | 0.261665 | 0.786322 | 0.363339 | 0.205527 | 0.542517 |
| 2 | 3 | 1599.0 | 1596.0 | 1753.0 | 5.019223 | 1.003845 | 0.502111 | 1.497189 | 0.812728 | 0.421693 | 1.222963 | 0.587491 | 0.272562 | 0.863676 |
| 3 | 4 | 1625.0 | 1601.0 | 1220.0 | 3.400038 | 0.850010 | 0.393685 | 1.097105 | 0.676622 | 0.310693 | 0.887855 | 0.514248 | 0.241781 | 0.654661 |
| 4 | 5 | 1602.0 | 1576.0 | 1536.0 | 2.816980 | 0.704245 | 0.428064 | 1.110873 | 0.563238 | 0.324563 | 0.892957 | 0.421998 | 0.279102 | 0.660807 |
data.shape
(2470, 14)
Коэффициент мощности прямо пропорционален активной мощности и также не является аддитивной величиной. Поэтому к набору данных можно добавить только статистические показатели: среднее арифметическое, минимум и максимум значений коэффициента мощности.
data = data.merge(
data_arc.groupby('key')['power_factor']
.agg(['mean', 'min', 'max']).reset_index()
.rename(
{'mean': 'power_factor_avg',
'min': 'power_factor_min',
'max': 'power_factor_max'}, axis=1),
on='key')
data.head()
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | active_power_avg | active_power_min | active_power_max | reactive_power_avg | reactive_power_min | reactive_power_max | power_factor_avg | power_factor_min | power_factor_max | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 | 3.718736 | 0.743747 | 0.371123 | 1.079934 | 0.607346 | 0.305130 | 0.867133 | 0.428564 | 0.211253 | 0.643691 | 0.816686 | 0.802950 | 0.848545 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 | 2.588349 | 0.647087 | 0.332731 | 0.955315 | 0.534852 | 0.261665 | 0.786322 | 0.363339 | 0.205527 | 0.542517 | 0.825276 | 0.786416 | 0.865721 |
| 2 | 3 | 1599.0 | 1596.0 | 1753.0 | 5.019223 | 1.003845 | 0.502111 | 1.497189 | 0.812728 | 0.421693 | 1.222963 | 0.587491 | 0.272562 | 0.863676 | 0.809724 | 0.752692 | 0.839841 |
| 3 | 4 | 1625.0 | 1601.0 | 1220.0 | 3.400038 | 0.850010 | 0.393685 | 1.097105 | 0.676622 | 0.310693 | 0.887855 | 0.514248 | 0.241781 | 0.654661 | 0.793923 | 0.779854 | 0.809271 |
| 4 | 5 | 1602.0 | 1576.0 | 1536.0 | 2.816980 | 0.704245 | 0.428064 | 1.110873 | 0.563238 | 0.324563 | 0.892957 | 0.421998 | 0.279102 | 0.660807 | 0.796818 | 0.758211 | 0.831286 |
data.shape
(2470, 17)
Время подогрева — это время, в течение которого на электроды подавалось напряжение, и они сообщали энергию расплаву. Можно рассчитать суммарное время передачи энергии электродами, а также статистические показатели: среднее арифметическое, минимум и максимум значений времени подогрева, и количество таких операций.
data = data.merge(
data_arc.groupby('key')['heating_time']
.agg(['sum', 'mean', 'min', 'max', 'count']).reset_index()
.rename(
{'sum': 'heating_time_sum',
'mean': 'heating_time_avg',
'min': 'heating_time_min',
'max': 'heating_time_max',
'count': 'heating_count'}, axis=1),
on='key')
data.head()
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | active_power_avg | active_power_min | active_power_max | reactive_power_avg | reactive_power_min | reactive_power_max | power_factor_avg | power_factor_min | power_factor_max | heating_time_sum | heating_time_avg | heating_time_min | heating_time_max | heating_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 | 3.718736 | 0.743747 | 0.371123 | 1.079934 | 0.607346 | 0.305130 | 0.867133 | 0.428564 | 0.211253 | 0.643691 | 0.816686 | 0.802950 | 0.848545 | 1098.0 | 219.60 | 148.0 | 365.0 | 5 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 | 2.588349 | 0.647087 | 0.332731 | 0.955315 | 0.534852 | 0.261665 | 0.786322 | 0.363339 | 0.205527 | 0.542517 | 0.825276 | 0.786416 | 0.865721 | 811.0 | 202.75 | 126.0 | 338.0 | 4 |
| 2 | 3 | 1599.0 | 1596.0 | 1753.0 | 5.019223 | 1.003845 | 0.502111 | 1.497189 | 0.812728 | 0.421693 | 1.222963 | 0.587491 | 0.272562 | 0.863676 | 0.809724 | 0.752692 | 0.839841 | 655.0 | 131.00 | 65.0 | 280.0 | 5 |
| 3 | 4 | 1625.0 | 1601.0 | 1220.0 | 3.400038 | 0.850010 | 0.393685 | 1.097105 | 0.676622 | 0.310693 | 0.887855 | 0.514248 | 0.241781 | 0.654661 | 0.793923 | 0.779854 | 0.809271 | 741.0 | 185.25 | 99.0 | 278.0 | 4 |
| 4 | 5 | 1602.0 | 1576.0 | 1536.0 | 2.816980 | 0.704245 | 0.428064 | 1.110873 | 0.563238 | 0.324563 | 0.892957 | 0.421998 | 0.279102 | 0.660807 | 0.796818 | 0.758211 | 0.831286 | 869.0 | 217.25 | 71.0 | 415.0 | 4 |
data.shape
(2470, 22)
Для энергии также допустимо рассчитывать сумму значений энергии, сообщённой электродами расплаву на каждой операции подогрева. Кроме того, можно рассчитать статистические показатели: среднее арифметическое, минимум и максимум значений потреблённой энергии.
data = data.merge(
data_arc.groupby('key')['energy']
.agg(['sum', 'mean', 'min', 'max']).reset_index()
.rename(
{'sum': 'energy_sum',
'mean': 'energy_avg',
'min': 'energy_min',
'max': 'energy_max'}, axis=1),
on='key')
data.head()
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | active_power_avg | active_power_min | active_power_max | reactive_power_avg | reactive_power_min | reactive_power_max | power_factor_avg | power_factor_min | power_factor_max | heating_time_sum | heating_time_avg | heating_time_min | heating_time_max | heating_count | energy_sum | energy_avg | energy_min | energy_max | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 | 3.718736 | 0.743747 | 0.371123 | 1.079934 | 0.607346 | 0.305130 | 0.867133 | 0.428564 | 0.211253 | 0.643691 | 0.816686 | 0.802950 | 0.848545 | 1098.0 | 219.60 | 148.0 | 365.0 | 5 | 770.282114 | 154.056423 | 84.616003 | 234.630603 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 | 2.588349 | 0.647087 | 0.332731 | 0.955315 | 0.534852 | 0.261665 | 0.786322 | 0.363339 | 0.205527 | 0.542517 | 0.825276 | 0.786416 | 0.865721 | 811.0 | 202.75 | 126.0 | 338.0 | 4 | 481.760005 | 120.440001 | 60.312695 | 200.616176 |
| 2 | 3 | 1599.0 | 1596.0 | 1753.0 | 5.019223 | 1.003845 | 0.502111 | 1.497189 | 0.812728 | 0.421693 | 1.222963 | 0.587491 | 0.272562 | 0.863676 | 0.809724 | 0.752692 | 0.839841 | 655.0 | 131.00 | 65.0 | 280.0 | 5 | 722.837668 | 144.567534 | 32.637187 | 384.681584 |
| 3 | 4 | 1625.0 | 1601.0 | 1220.0 | 3.400038 | 0.850010 | 0.393685 | 1.097105 | 0.676622 | 0.310693 | 0.887855 | 0.514248 | 0.241781 | 0.654661 | 0.793923 | 0.779854 | 0.809271 | 741.0 | 185.25 | 99.0 | 278.0 | 4 | 683.455597 | 170.863899 | 38.974854 | 301.575212 |
| 4 | 5 | 1602.0 | 1576.0 | 1536.0 | 2.816980 | 0.704245 | 0.428064 | 1.110873 | 0.563238 | 0.324563 | 0.892957 | 0.421998 | 0.279102 | 0.660807 | 0.796818 | 0.758211 | 0.831286 | 869.0 | 217.25 | 71.0 | 415.0 | 4 | 512.169934 | 128.042484 | 78.871960 | 230.452869 |
data.shape
(2470, 26)
Добавим к набору данных сведения об объёме пропущенного через расплав инертного газа.
data = data.merge(data_gas, on='key').rename({'Газ 1': 'gas'}, axis=1)
data.head()
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | active_power_avg | active_power_min | active_power_max | reactive_power_avg | reactive_power_min | reactive_power_max | power_factor_avg | power_factor_min | power_factor_max | heating_time_sum | heating_time_avg | heating_time_min | heating_time_max | heating_count | energy_sum | energy_avg | energy_min | energy_max | gas | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 | 3.718736 | 0.743747 | 0.371123 | 1.079934 | 0.607346 | 0.305130 | 0.867133 | 0.428564 | 0.211253 | 0.643691 | 0.816686 | 0.802950 | 0.848545 | 1098.0 | 219.60 | 148.0 | 365.0 | 5 | 770.282114 | 154.056423 | 84.616003 | 234.630603 | 29.749986 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 | 2.588349 | 0.647087 | 0.332731 | 0.955315 | 0.534852 | 0.261665 | 0.786322 | 0.363339 | 0.205527 | 0.542517 | 0.825276 | 0.786416 | 0.865721 | 811.0 | 202.75 | 126.0 | 338.0 | 4 | 481.760005 | 120.440001 | 60.312695 | 200.616176 | 12.555561 |
| 2 | 3 | 1599.0 | 1596.0 | 1753.0 | 5.019223 | 1.003845 | 0.502111 | 1.497189 | 0.812728 | 0.421693 | 1.222963 | 0.587491 | 0.272562 | 0.863676 | 0.809724 | 0.752692 | 0.839841 | 655.0 | 131.00 | 65.0 | 280.0 | 5 | 722.837668 | 144.567534 | 32.637187 | 384.681584 | 28.554793 |
| 3 | 4 | 1625.0 | 1601.0 | 1220.0 | 3.400038 | 0.850010 | 0.393685 | 1.097105 | 0.676622 | 0.310693 | 0.887855 | 0.514248 | 0.241781 | 0.654661 | 0.793923 | 0.779854 | 0.809271 | 741.0 | 185.25 | 99.0 | 278.0 | 4 | 683.455597 | 170.863899 | 38.974854 | 301.575212 | 18.841219 |
| 4 | 5 | 1602.0 | 1576.0 | 1536.0 | 2.816980 | 0.704245 | 0.428064 | 1.110873 | 0.563238 | 0.324563 | 0.892957 | 0.421998 | 0.279102 | 0.660807 | 0.796818 | 0.758211 | 0.831286 | 869.0 | 217.25 | 71.0 | 415.0 | 4 | 512.169934 | 128.042484 | 78.871960 | 230.452869 | 5.413692 |
data.shape
(2468, 27)
Добавим к набору данных сведения о массе каждого из добавленных сыпучих материалов, общей массе сыпучих материалов и о количестве их различных видов.
data = data.merge(data_bulk, on='key')
data.head()
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | active_power_avg | active_power_min | active_power_max | reactive_power_avg | reactive_power_min | reactive_power_max | power_factor_avg | power_factor_min | power_factor_max | heating_time_sum | heating_time_avg | heating_time_min | heating_time_max | heating_count | energy_sum | energy_avg | energy_min | energy_max | gas | bulk_1 | bulk_2 | bulk_3 | bulk_4 | bulk_5 | bulk_6 | bulk_7 | bulk_8 | bulk_9 | bulk_10 | bulk_11 | bulk_12 | bulk_13 | bulk_14 | bulk_15 | bulk_sum | bulk_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 | 3.718736 | 0.743747 | 0.371123 | 1.079934 | 0.607346 | 0.305130 | 0.867133 | 0.428564 | 0.211253 | 0.643691 | 0.816686 | 0.802950 | 0.848545 | 1098.0 | 219.60 | 148.0 | 365.0 | 5 | 770.282114 | 154.056423 | 84.616003 | 234.630603 | 29.749986 | 0.0 | 0.0 | 0.0 | 43.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 206.0 | 0.0 | 150.0 | 154.0 | 553.0 | 4 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 | 2.588349 | 0.647087 | 0.332731 | 0.955315 | 0.534852 | 0.261665 | 0.786322 | 0.363339 | 0.205527 | 0.542517 | 0.825276 | 0.786416 | 0.865721 | 811.0 | 202.75 | 126.0 | 338.0 | 4 | 481.760005 | 120.440001 | 60.312695 | 200.616176 | 12.555561 | 0.0 | 0.0 | 0.0 | 73.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 206.0 | 0.0 | 149.0 | 154.0 | 582.0 | 4 |
| 2 | 3 | 1599.0 | 1596.0 | 1753.0 | 5.019223 | 1.003845 | 0.502111 | 1.497189 | 0.812728 | 0.421693 | 1.222963 | 0.587491 | 0.272562 | 0.863676 | 0.809724 | 0.752692 | 0.839841 | 655.0 | 131.00 | 65.0 | 280.0 | 5 | 722.837668 | 144.567534 | 32.637187 | 384.681584 | 28.554793 | 0.0 | 0.0 | 0.0 | 34.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 205.0 | 0.0 | 152.0 | 153.0 | 544.0 | 4 |
| 3 | 4 | 1625.0 | 1601.0 | 1220.0 | 3.400038 | 0.850010 | 0.393685 | 1.097105 | 0.676622 | 0.310693 | 0.887855 | 0.514248 | 0.241781 | 0.654661 | 0.793923 | 0.779854 | 0.809271 | 741.0 | 185.25 | 99.0 | 278.0 | 4 | 683.455597 | 170.863899 | 38.974854 | 301.575212 | 18.841219 | 0.0 | 0.0 | 0.0 | 81.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 207.0 | 0.0 | 153.0 | 154.0 | 595.0 | 4 |
| 4 | 5 | 1602.0 | 1576.0 | 1536.0 | 2.816980 | 0.704245 | 0.428064 | 1.110873 | 0.563238 | 0.324563 | 0.892957 | 0.421998 | 0.279102 | 0.660807 | 0.796818 | 0.758211 | 0.831286 | 869.0 | 217.25 | 71.0 | 415.0 | 4 | 512.169934 | 128.042484 | 78.871960 | 230.452869 | 5.413692 | 0.0 | 0.0 | 0.0 | 78.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 203.0 | 0.0 | 151.0 | 152.0 | 584.0 | 4 |
data.shape
(2400, 44)
Также добавим к набору данных сведения о массе проволочных материалов, общей добавленной массе и о количестве их различных видов.
data = data.merge(data_wire, on='key')
data.head()
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | active_power_avg | active_power_min | active_power_max | reactive_power_avg | reactive_power_min | reactive_power_max | power_factor_avg | power_factor_min | power_factor_max | heating_time_sum | heating_time_avg | heating_time_min | heating_time_max | heating_count | energy_sum | energy_avg | energy_min | energy_max | gas | bulk_1 | bulk_2 | bulk_3 | bulk_4 | bulk_5 | bulk_6 | bulk_7 | bulk_8 | bulk_9 | bulk_10 | bulk_11 | bulk_12 | bulk_13 | bulk_14 | bulk_15 | bulk_sum | bulk_count | wire_1 | wire_2 | wire_3 | wire_4 | wire_5 | wire_6 | wire_7 | wire_8 | wire_9 | wire_sum | wire_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 | 3.718736 | 0.743747 | 0.371123 | 1.079934 | 0.607346 | 0.305130 | 0.867133 | 0.428564 | 0.211253 | 0.643691 | 0.816686 | 0.802950 | 0.848545 | 1098.0 | 219.60 | 148.0 | 365.0 | 5 | 770.282114 | 154.056423 | 84.616003 | 234.630603 | 29.749986 | 0.0 | 0.0 | 0.0 | 43.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 206.0 | 0.0 | 150.0 | 154.0 | 553.0 | 4 | 60.059998 | 0.00000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 60.059998 | 1 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 | 2.588349 | 0.647087 | 0.332731 | 0.955315 | 0.534852 | 0.261665 | 0.786322 | 0.363339 | 0.205527 | 0.542517 | 0.825276 | 0.786416 | 0.865721 | 811.0 | 202.75 | 126.0 | 338.0 | 4 | 481.760005 | 120.440001 | 60.312695 | 200.616176 | 12.555561 | 0.0 | 0.0 | 0.0 | 73.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 206.0 | 0.0 | 149.0 | 154.0 | 582.0 | 4 | 96.052315 | 0.00000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 96.052315 | 1 |
| 2 | 3 | 1599.0 | 1596.0 | 1753.0 | 5.019223 | 1.003845 | 0.502111 | 1.497189 | 0.812728 | 0.421693 | 1.222963 | 0.587491 | 0.272562 | 0.863676 | 0.809724 | 0.752692 | 0.839841 | 655.0 | 131.00 | 65.0 | 280.0 | 5 | 722.837668 | 144.567534 | 32.637187 | 384.681584 | 28.554793 | 0.0 | 0.0 | 0.0 | 34.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 205.0 | 0.0 | 152.0 | 153.0 | 544.0 | 4 | 91.160157 | 0.00000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 91.160157 | 1 |
| 3 | 4 | 1625.0 | 1601.0 | 1220.0 | 3.400038 | 0.850010 | 0.393685 | 1.097105 | 0.676622 | 0.310693 | 0.887855 | 0.514248 | 0.241781 | 0.654661 | 0.793923 | 0.779854 | 0.809271 | 741.0 | 185.25 | 99.0 | 278.0 | 4 | 683.455597 | 170.863899 | 38.974854 | 301.575212 | 18.841219 | 0.0 | 0.0 | 0.0 | 81.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 207.0 | 0.0 | 153.0 | 154.0 | 595.0 | 4 | 89.063515 | 0.00000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 89.063515 | 1 |
| 4 | 5 | 1602.0 | 1576.0 | 1536.0 | 2.816980 | 0.704245 | 0.428064 | 1.110873 | 0.563238 | 0.324563 | 0.892957 | 0.421998 | 0.279102 | 0.660807 | 0.796818 | 0.758211 | 0.831286 | 869.0 | 217.25 | 71.0 | 415.0 | 4 | 512.169934 | 128.042484 | 78.871960 | 230.452869 | 5.413692 | 0.0 | 0.0 | 0.0 | 78.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 203.0 | 0.0 | 151.0 | 152.0 | 584.0 | 4 | 89.238236 | 9.11456 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 98.352796 | 2 |
data.shape
(2324, 55)
df_info(data)
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | active_power_avg | active_power_min | active_power_max | reactive_power_avg | reactive_power_min | reactive_power_max | power_factor_avg | power_factor_min | power_factor_max | heating_time_sum | heating_time_avg | heating_time_min | heating_time_max | heating_count | energy_sum | energy_avg | energy_min | energy_max | gas | bulk_1 | bulk_2 | bulk_3 | bulk_4 | bulk_5 | bulk_6 | bulk_7 | bulk_8 | bulk_9 | bulk_10 | bulk_11 | bulk_12 | bulk_13 | bulk_14 | bulk_15 | bulk_sum | bulk_count | wire_1 | wire_2 | wire_3 | wire_4 | wire_5 | wire_6 | wire_7 | wire_8 | wire_9 | wire_sum | wire_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1613.0 | 1571.0 | 1714.0 | 3.718736 | 0.743747 | 0.371123 | 1.079934 | 0.607346 | 0.305130 | 0.867133 | 0.428564 | 0.211253 | 0.643691 | 0.816686 | 0.802950 | 0.848545 | 1098.0 | 219.60 | 148.0 | 365.0 | 5 | 770.282114 | 154.056423 | 84.616003 | 234.630603 | 29.749986 | 0.0 | 0.0 | 0.0 | 43.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 206.0 | 0.0 | 150.0 | 154.0 | 553.0 | 4 | 60.059998 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 60.059998 | 1 |
| 1 | 2 | 1602.0 | 1581.0 | 1265.0 | 2.588349 | 0.647087 | 0.332731 | 0.955315 | 0.534852 | 0.261665 | 0.786322 | 0.363339 | 0.205527 | 0.542517 | 0.825276 | 0.786416 | 0.865721 | 811.0 | 202.75 | 126.0 | 338.0 | 4 | 481.760005 | 120.440001 | 60.312695 | 200.616176 | 12.555561 | 0.0 | 0.0 | 0.0 | 73.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 206.0 | 0.0 | 149.0 | 154.0 | 582.0 | 4 | 96.052315 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 96.052315 | 1 |
| key | last_temperature | first_temperature | process_time | full_power_sum | full_power_avg | full_power_min | full_power_max | active_power_avg | active_power_min | active_power_max | reactive_power_avg | reactive_power_min | reactive_power_max | power_factor_avg | power_factor_min | power_factor_max | heating_time_sum | heating_time_avg | heating_time_min | heating_time_max | heating_count | energy_sum | energy_avg | energy_min | energy_max | gas | bulk_1 | bulk_2 | bulk_3 | bulk_4 | bulk_5 | bulk_6 | bulk_7 | bulk_8 | bulk_9 | bulk_10 | bulk_11 | bulk_12 | bulk_13 | bulk_14 | bulk_15 | bulk_sum | bulk_count | wire_1 | wire_2 | wire_3 | wire_4 | wire_5 | wire_6 | wire_7 | wire_8 | wire_9 | wire_sum | wire_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2322 | 2498 | 1594.0 | 1591.0 | 1520.0 | 3.909917 | 0.781983 | 0.512900 | 1.190819 | 0.640462 | 0.419017 | 0.999939 | 0.447964 | 0.289814 | 0.646662 | 0.819245 | 0.793073 | 0.839707 | 750.0 | 150.00 | 41.0 | 256.0 | 5 | 581.810739 | 116.362148 | 25.647067 | 203.935064 | 14.953657 | 0.0 | 0.0 | 90.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 101.0 | 0.0 | 206.0 | 0.0 | 129.0 | 207.0 | 733.0 | 5 | 118.110717 | 0.00000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 118.110717 | 1 |
| 2323 | 2499 | 1603.0 | 1569.0 | 1537.0 | 2.169252 | 0.542313 | 0.374585 | 0.881433 | 0.434271 | 0.296379 | 0.700677 | 0.324209 | 0.229071 | 0.534767 | 0.800782 | 0.777820 | 0.839161 | 883.0 | 220.75 | 71.0 | 312.0 | 4 | 532.386183 | 133.096546 | 26.595546 | 275.007073 | 11.336151 | 0.0 | 0.0 | 47.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 233.0 | 0.0 | 126.0 | 227.0 | 633.0 | 4 | 110.160958 | 50.00528 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 160.166238 | 2 |
Размер набора данных: (2324, 55) Количество элементов данных: 127820 Количество дубликатов в наименованиях признаков: 0 Уникальные наименования признаков: ['active_power_avg', 'active_power_max', 'active_power_min', 'bulk_1', 'bulk_10', 'bulk_11', 'bulk_12', 'bulk_13', 'bulk_14', 'bulk_15', 'bulk_2', 'bulk_3', 'bulk_4', 'bulk_5', 'bulk_6', 'bulk_7', 'bulk_8', 'bulk_9', 'bulk_count', 'bulk_sum', 'energy_avg', 'energy_max', 'energy_min', 'energy_sum', 'first_temperature', 'full_power_avg', 'full_power_max', 'full_power_min', 'full_power_sum', 'gas', 'heating_count', 'heating_time_avg', 'heating_time_max', 'heating_time_min', 'heating_time_sum', 'key', 'last_temperature', 'power_factor_avg', 'power_factor_max', 'power_factor_min', 'process_time', 'reactive_power_avg', 'reactive_power_max', 'reactive_power_min', 'wire_1', 'wire_2', 'wire_3', 'wire_4', 'wire_5', 'wire_6', 'wire_7', 'wire_8', 'wire_9', 'wire_count', 'wire_sum'] Количество пропущенных значений: 0 Процент пропущенных значений: 0.0 % Типы данных набора данных:
float64 51 int64 4 dtype: int64
Проверим, согласуются ли записи в признаках process_time и heating_time_sum. Время проведения процесса легирования не должно быть меньше времени подогрева расплава.
sum(data['process_time'] <= data['heating_time_sum'])
0
Проверим количество полных дублей. Неявные дубликаты в наборе данных присутствовать не могут априори, поскольку каждая запись характеризует отдельную партию, и сбор исходных данных был распределён во времени.
data.duplicated().sum()
0
Данные о партиях
descriptive_statistics(
data['first_temperature'], 'Начальная температура, \u2103').join(
descriptive_statistics(
data['last_temperature'], 'Конечная температура, \u2103'))
| Начальная температура, ℃ | Конечная температура, ℃ | |
|---|---|---|
| кол-во значений | 2324 | 2324 |
| кол-во уникальных | 133 | 75 |
| мин. | 1519.0 | 1541.0 |
| -1.5IQR | 1539.0 | 1576.5 |
| 25 % | 1571.0 | 1587.0 |
| мода | [1588.0] | [1593.0] |
| медиана | 1587.0 | 1593.0 |
| среднее ариф. | 1587.37 | 1593.37 |
| 75 % | 1603.0 | 1598.0 |
| +1.5IQR | 1635.0 | 1609.5 |
| макс. | 1660.0 | 1653.0 |
| размах | 141.0 | 112.0 |
| межквартильный размах | 32.0 | 11.0 |
label = ['Конечная температура', 'Начальная температура']
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['last_temperature'], color='coral')
sns.kdeplot(data['first_temperature'], color='gold', shade=True)
plt.xlabel('Температура, \u2103')
plt.ylabel('Плотность распределения')
plt.legend(label)
plt.show()
last_temperature — конечная температура ($^{\circ}$C)
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
first_temperature — начальная температура ($^{\circ}$C)
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
descriptive_statistics(data['process_time'], 'Время легирования, с')
| Время легирования, с | |
|---|---|
| кол-во значений | 2324 |
| кол-во уникальных | 1630 |
| мин. | 339.0 |
| -1.5IQR | 227.0 |
| 25 % | 1580.5 |
| мода | [1598.0, 1603.0] |
| медиана | 2046.5 |
| среднее ариф. | 2323.68 |
| 75 % | 2793.5 |
| +1.5IQR | 3866.0 |
| макс. | 23674.0 |
| размах | 23335.0 |
| межквартильный размах | 1213.0 |
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['process_time'], color='gold', shade=True)
plt.xlabel('Время легирования, с')
plt.ylabel('Плотность распределения')
plt.show()
process_time — время легирования (с)
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
descriptive_statistics(data['full_power_sum'], 'Полная мощность, МВт')
| Полная мощность, МВт | |
|---|---|
| кол-во значений | 2324 |
| кол-во уникальных | 2324 |
| мин. | 0.331897 |
| -1.5IQR | 0.886293 |
| 25 % | 2.85 |
| мода | [0.3318973771514322, 0.42767528909208674, 0.50... |
| медиана | 3.77 |
| среднее ариф. | 3.89 |
| 75 % | 4.77 |
| +1.5IQR | 6.654875 |
| макс. | 15.288271 |
| размах | 14.956374 |
| межквартильный размах | 1.922861 |
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['full_power_sum'], color='gold', shade=True)
plt.xlabel('Полная мощность (на стадию легирования), МВт')
plt.ylabel('Плотность распределения')
plt.show()
full_power_sum — суммарное значение полной мощности (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
col_name = 'Полная мощность, развиваемая за одну операцию подогрева, МВт'
pd.DataFrame(descriptive_statistics(
data['full_power_min'], 'Минимальное значение').join(
descriptive_statistics(
data['full_power_avg'], 'Среднее значение')).join(
descriptive_statistics(
data['full_power_max'], 'Максимальное значение'))
).rename_axis(col_name, axis=1)
| Полная мощность, развиваемая за одну операцию подогрева, МВт | Минимальное значение | Среднее значение | Максимальное значение |
|---|---|---|---|
| кол-во значений | 2324 | 2324 | 2324 |
| кол-во уникальных | 2324 | 2324 | 2324 |
| мин. | 0.275718 | 0.331897 | 0.331897 |
| -1.5IQR | 0.233768 | 0.507749 | 0.540493 |
| 25 % | 0.41 | 0.71 | 0.99 |
| мода | [0.2757183411255044, 0.2836848387154308, 0.285... | [0.3318973771514322, 0.3813739286828069, 0.399... | [0.3318973771514322, 0.40681076007033046, 0.42... |
| медиана | 0.5 | 0.82 | 1.21 |
| среднее ариф. | 0.52 | 0.83 | 1.21 |
| 75 % | 0.6 | 0.92 | 1.44 |
| +1.5IQR | 0.774966 | 1.128855 | 1.872782 |
| макс. | 1.429109 | 1.572238 | 1.898158 |
| размах | 1.153391 | 1.240341 | 1.566261 |
| межквартильный размах | 0.180399 | 0.207035 | 0.444097 |
label = ['Минимальное значение', 'Среднее значение', 'Максимальное значение']
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['full_power_min'], color='coral')
sns.kdeplot(data['full_power_avg'], color='gold', shade=True)
sns.kdeplot(data['full_power_max'], color='sienna')
plt.xlabel('Полная мощность (на операцию подогрева), МВт')
plt.ylabel('Плотность распределения')
plt.legend(label)
plt.show()
full_power_min — минимальное значение полной мощности для одной операции подогрева расплава (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
full_power_avg — среднее значение полной мощности для одной операции подогрева расплава (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
full_power_max — максимальное значение полной мощности для одной операции подогрева расплава (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
col_name = 'Активная мощность, развиваемая за одну операцию подогрева, МВт'
pd.DataFrame(descriptive_statistics(
data['active_power_min'], 'Минимальное значение').join(
descriptive_statistics(
data['active_power_avg'], 'Среднее значение')).join(
descriptive_statistics(
data['active_power_max'], 'Максимальное значение'))
).rename_axis(col_name, axis=1)
| Активная мощность, развиваемая за одну операцию подогрева, МВт | Минимальное значение | Среднее значение | Максимальное значение |
|---|---|---|---|
| кол-во значений | 2324 | 2324 | 2324 |
| кол-во уникальных | 2253 | 2323 | 2264 |
| мин. | 0.223895 | 0.267676 | 0.267676 |
| -1.5IQR | 0.188311 | 0.407249 | 0.43934 |
| 25 % | 0.33 | 0.58 | 0.8 |
| мода | [0.304755] | [0.557008] | [0.603421, 0.617319, 0.67913, 0.7157, 0.750905... |
| медиана | 0.41 | 0.66 | 0.97 |
| среднее ариф. | 0.42 | 0.66 | 0.97 |
| 75 % | 0.48 | 0.74 | 1.16 |
| +1.5IQR | 0.62552 | 0.90442 | 1.504835 |
| макс. | 1.140738 | 1.243889 | 1.463773 |
| размах | 0.916843 | 0.976213 | 1.196097 |
| межквартильный размах | 0.145736 | 0.165724 | 0.355165 |
label = ['Минимальное значение', 'Среднее значение', 'Максимальное значение']
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['active_power_min'], color='coral')
sns.kdeplot(data['active_power_avg'], color='gold', shade=True)
sns.kdeplot(data['active_power_max'], color='sienna')
plt.xlabel('Активная мощность (на операцию подогрева), МВт')
plt.ylabel('Плотность распределения')
plt.legend(label)
plt.show()
active_power_min — минимальное значение активной мощности для одной операции подогрева расплава (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
active_power_avg — среднее значение активной мощности для одной операции подогрева расплава (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
active_power_max — максимальное значение активной мощности для одной операции подогрева расплава (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
col_name = 'Реактивная мощность, развиваемая за одну операцию подогрева, МВт'
pd.DataFrame(descriptive_statistics(
data['reactive_power_min'], 'Минимальное значение').join(
descriptive_statistics(
data['reactive_power_avg'], 'Среднее значение')).join(
descriptive_statistics(
data['reactive_power_max'], 'Максимальное значение'))
).rename_axis(col_name, axis=1)
| Реактивная мощность, развиваемая за одну операцию подогрева, МВт | Минимальное значение | Среднее значение | Максимальное значение |
|---|---|---|---|
| кол-во значений | 2324 | 2324 | 2324 |
| кол-во уникальных | 2309 | 2323 | 2323 |
| мин. | 0.153777 | 0.196228 | 0.196228 |
| -1.5IQR | 0.127236 | 0.294688 | 0.317754 |
| 25 % | 0.24 | 0.42 | 0.59 |
| мода | [0.257418] | [0.5403865] | [0.530982] |
| медиана | 0.29 | 0.48 | 0.72 |
| среднее ариф. | 0.3 | 0.49 | 0.72 |
| 75 % | 0.35 | 0.55 | 0.85 |
| +1.5IQR | 0.456545 | 0.674649 | 1.114011 |
| макс. | 0.875916 | 0.960763 | 1.270284 |
| размах | 0.722139 | 0.764535 | 1.074056 |
| межквартильный размах | 0.109769 | 0.126654 | 0.265419 |
label = ['Минимальное значение', 'Среднее значение', 'Максимальное значение']
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['reactive_power_min'], color='coral')
sns.kdeplot(data['reactive_power_avg'], color='gold', shade=True)
sns.kdeplot(data['reactive_power_max'], color='sienna')
plt.xlabel('Реактивная мощность (на операцию подогрева), МВт')
plt.ylabel('Плотность распределения')
plt.legend(label)
plt.show()
reactive_power_min — минимальное значение реактивной мощности для одной операции подогрева расплава (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
reactive_power_avg — среднее значение реактивной мощности для одной операции подогрева расплава (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
reactive_power_max — максимальное значение реактивной мощности для одной операции подогрева расплава (МВт)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
col_name = 'Коэффициент мощности, развиваемой за одну операцию подогрева'
pd.DataFrame(descriptive_statistics(
data['power_factor_min'], 'Минимальное значение').join(
descriptive_statistics(
data['power_factor_avg'], 'Среднее значение')).join(
descriptive_statistics(
data['power_factor_max'], 'Максимальное значение'))
).rename_axis(col_name, axis=1)
| Коэффициент мощности, развиваемой за одну операцию подогрева | Минимальное значение | Среднее значение | Максимальное значение |
|---|---|---|---|
| кол-во значений | 2324 | 2324 | 2324 |
| кол-во уникальных | 2324 | 2324 | 2324 |
| мин. | 0.707722 | 0.739789 | 0.743036 |
| -1.5IQR | 0.72065 | 0.779 | 0.807719 |
| 25 % | 0.76 | 0.8 | 0.82 |
| мода | [0.707722024438604, 0.7119254667035388, 0.7139... | [0.7397892461266198, 0.7422799682440981, 0.743... | [0.7430360587816858, 0.7436744060245243, 0.758... |
| медиана | 0.77 | 0.81 | 0.83 |
| среднее ариф. | 0.77 | 0.81 | 0.83 |
| 75 % | 0.79 | 0.81 | 0.84 |
| +1.5IQR | 0.824254 | 0.833025 | 0.861821 |
| макс. | 0.857042 | 0.857042 | 0.870445 |
| размах | 0.14932 | 0.117253 | 0.127409 |
| межквартильный размах | 0.034535 | 0.018008 | 0.018034 |
label = ['Минимальное значение', 'Среднее значение', 'Максимальное значение']
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['power_factor_min'], color='coral')
sns.kdeplot(data['power_factor_avg'], color='gold', shade=True)
sns.kdeplot(data['power_factor_max'], color='sienna')
plt.xlabel('Коэффициент мощности (на операцию подогрева)')
plt.ylabel('Плотность распределения')
plt.legend(label)
plt.show()
power_factor_min — минимальное значение коэффициента мощности для одной операции подогрева расплава
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
power_factor_avg — среднее значение коэффициента мощности для одной операции подогрева расплава
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
power_factor_max — максимальное значение коэффициента мощности для одной операции подогрева расплава
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
descriptive_statistics(data['heating_time_sum'], 'Время подогрева, с')
| Время подогрева, с | |
|---|---|
| кол-во значений | 2324 |
| кол-во уникальных | 1036 |
| мин. | 57.0 |
| -1.5IQR | 160.0 |
| 25 % | 581.0 |
| мода | [874.0] |
| медиана | 778.0 |
| среднее ариф. | 808.2 |
| 75 % | 993.0 |
| +1.5IQR | 1396.0 |
| макс. | 4189.0 |
| размах | 4132.0 |
| межквартильный размах | 412.0 |
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['heating_time_sum'], color='gold', shade=True)
plt.xlabel('Время подогрева, с')
plt.ylabel('Плотность распределения')
plt.show()
full_power_sum — суммарное значение времени подогрева в ходе одной стадии легирования (с)
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
col_name = 'Время одной операции подогрева, с'
pd.DataFrame(descriptive_statistics(
data['heating_time_min'], 'Минимальное значение, с').join(
descriptive_statistics(
data['heating_time_avg'], 'Среднее значение, с')).join(
descriptive_statistics(
data['heating_time_max'], 'Максимальное значение, с'))
).rename_axis(col_name, axis=1)
| Время одной операции подогрева, с | Минимальное значение, с | Среднее значение, с | Максимальное значение, с |
|---|---|---|---|
| кол-во значений | 2324 | 2324 | 2324 |
| кол-во уникальных | 197 | 1348 | 462 |
| мин. | 11.0 | 57.0 | 57.0 |
| -1.5IQR | 0.125 | 82.875 | 86.5 |
| 25 % | 62.0 | 141.0 | 212.0 |
| мода | [62.0] | [141.0, 173.0, 191.0] | [244.0] |
| медиана | 83.0 | 169.5 | 277.0 |
| среднее ариф. | 89.39 | 172.12 | 289.76 |
| 75 % | 117.25 | 198.75 | 339.0 |
| +1.5IQR | 165.875 | 256.125 | 467.5 |
| макс. | 281.0 | 378.0 | 907.0 |
| размах | 270.0 | 321.0 | 850.0 |
| межквартильный размах | 55.25 | 57.75 | 127.0 |
label = ['Минимальное значение', 'Среднее значение', 'Максимальное значение']
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['heating_time_min'], color='coral')
sns.kdeplot(data['heating_time_avg'], color='gold', shade=True)
sns.kdeplot(data['heating_time_max'], color='sienna')
plt.xlabel('Время одного подогрева, с')
plt.ylabel('Плотность распределения')
plt.legend(label)
plt.show()
heating_time_min — минимальное значение времени одной операции подогрева расплава (с)
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
heating_time_avg — среднее значение времени одной операции подогрева расплава (с)
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
heating_time_max — максимальное значение времени одной операции подогрева расплава (с)
Признак является количественным, непрерывным.
Шкала измерения признака: интервальная шкала.
descriptive_statistics(data['heating_count'], 'Количество операций подогрева')
| Количество операций подогрева | |
|---|---|
| кол-во значений | 2324 |
| кол-во уникальных | 15 |
| мин. | 1 |
| -1.5IQR | 2.0 |
| 25 % | 4.0 |
| мода | [4] |
| медиана | 5.0 |
| среднее ариф. | 4.7 |
| 75 % | 6.0 |
| +1.5IQR | 8.0 |
| макс. | 16 |
| размах | 15 |
| межквартильный размах | 2.0 |
plt.figure(figsize=(10, 3))
plt.title('График распределения значений количества операций подогрева')
data['heating_count'].value_counts().sort_index().plot(kind='bar',
color='gold',
rot=0)
plt.xlabel('Количество операций подогрева')
plt.ylabel('Частота')
plt.show()
heating_count — количество операций подогрева
Признак является количественным, дискретным.
Шкала измерения признака: абсолютная шкала.
descriptive_statistics(data['energy_sum'], 'Потреблённая энергия, МДж')
| Потреблённая энергия, МДж | |
|---|---|
| кол-во значений | 2324 |
| кол-во уникальных | 2324 |
| мин. | 33.430208 |
| -1.5IQR | 55.380027 |
| 25 % | 457.92 |
| мода | [33.43020759374457, 35.525857072478495, 41.487... |
| медиана | 631.23 |
| среднее ариф. | 670.23 |
| 75 % | 841.82 |
| +1.5IQR | 1207.077699 |
| макс. | 4546.405812 |
| размах | 4512.975605 |
| межквартильный размах | 383.899224 |
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['energy_sum'], color='gold', shade=True)
plt.xlabel('Потреблённая энергия (на стадию легирования), МДж')
plt.ylabel('Плотность распределения')
plt.show()
energy_sum — суммарное значение потреблённой энергии (МДж)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
col_name = 'Потребляемая за одну операцию подогрева энергия, МДж'
pd.DataFrame(descriptive_statistics(
data['energy_min'], 'Минимальное значение').join(
descriptive_statistics(
data['energy_avg'], 'Среднее значение')).join(
descriptive_statistics(
data['energy_max'], 'Максимальное значение'))
).rename_axis(col_name, axis=1)
| Потребляемая за одну операцию подогрева энергия, МДж | Минимальное значение | Среднее значение | Максимальное значение |
|---|---|---|---|
| кол-во значений | 2324 | 2324 | 2324 |
| кол-во уникальных | 2324 | 2324 | 2324 |
| мин. | 6.409531 | 25.227273 | 28.649852 |
| -1.5IQR | -3.282212 | 43.811574 | 12.822143 |
| 25 % | 38.54 | 108.96 | 175.08 |
| мода | [6.409530855986029, 6.501806548023787, 7.03108... | [25.227272609939007, 31.31340737231741, 33.430... | [28.64985159816941, 33.43020759374457, 35.5258... |
| медиана | 55.81 | 136.27 | 240.71 |
| среднее ариф. | 62.0 | 142.45 | 264.55 |
| 75 % | 77.94 | 170.6 | 327.01 |
| +1.5IQR | 114.905758 | 228.718856 | 468.589087 |
| макс. | 277.867924 | 436.387492 | 1069.548361 |
| размах | 271.458393 | 411.160219 | 1040.898509 |
| межквартильный размах | 39.39599 | 61.635761 | 151.922315 |
label = ['Минимальное значение', 'Среднее значение', 'Максимальное значение']
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['energy_min'], color='coral')
sns.kdeplot(data['energy_avg'], color='gold', shade=True)
sns.kdeplot(data['energy_max'], color='sienna')
plt.xlabel('Потребляемая энергия (за операцию подогрева), МДж')
plt.ylabel('Плотность распределения')
plt.legend(label)
plt.show()
energy_min — минимальное значение энергии, потребляемой за одну операцию подогрева расплава (МДж)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
energy_avg — среднее значение энергии, потребляемой за одну операцию подогрева расплава (МДж)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
energy_max — максимальное значение энергии, потребляемой за одну операцию подогрева расплава (МДж)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
descriptive_statistics(data['gas'], 'Объём инертного газа, м$^3$')
| Объём инертного газа, м$^3$ | |
|---|---|
| кол-во значений | 2324 |
| кол-во уникальных | 2324 |
| мин. | 0.008399 |
| -1.5IQR | -0.303242 |
| 25 % | 7.28 |
| мода | [0.0083985291, 0.0166956024, 0.3642557946, 0.8... |
| медиана | 10.1 |
| среднее ариф. | 11.38 |
| 75 % | 14.22 |
| +1.5IQR | 20.504615 |
| макс. | 77.99504 |
| размах | 77.986641 |
| межквартильный размах | 6.935952 |
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['gas'], color='gold', shade=True)
plt.xlabel('Объём инертного газа, м$^3$')
plt.ylabel('Плотность распределения')
plt.show()
gas — суммарное значение полной мощности (м$^3$)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
descriptive_statistics(data['bulk_sum'], 'Общая масса сыпучих материалов, кг')
| Общая масса сыпучих материалов, кг | |
|---|---|
| кол-во значений | 2324 |
| кол-во уникальных | 963 |
| мин. | 19.0 |
| -1.5IQR | 75.0 |
| 25 % | 440.0 |
| мода | [582.0] |
| медиана | 609.0 |
| среднее ариф. | 610.08 |
| 75 % | 796.0 |
| +1.5IQR | 1143.0 |
| макс. | 3235.0 |
| размах | 3216.0 |
| межквартильный размах | 356.0 |
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['bulk_sum'], color='gold', shade=True)
plt.xlabel('Общая масса сыпучих материалов, кг')
plt.ylabel('Плотность распределения')
plt.show()
bulk_sum — общая масса сыпучих материалов (кг)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
descriptive_statistics(
data['bulk_count'], 'Количество разных видов внесённых сыпучих материалов')
| Количество разных видов внесённых сыпучих материалов | |
|---|---|
| кол-во значений | 2324 |
| кол-во уникальных | 7 |
| мин. | 1 |
| -1.5IQR | 2.5 |
| 25 % | 3.0 |
| мода | [4] |
| медиана | 4.0 |
| среднее ариф. | 3.59 |
| 75 % | 4.0 |
| +1.5IQR | 5.5 |
| макс. | 7 |
| размах | 6 |
| межквартильный размах | 1.0 |
plt.figure(figsize=(10, 3))
plt.title('График распределения значений количества операций подогрева')
data['bulk_count'].value_counts().sort_index().plot(kind='bar',
color='gold',
rot=0)
plt.xlabel('Количество разных видов внесённых сыпучих материалов')
plt.ylabel('Частота')
plt.show()
bulk_count — количество разных видов внесённых сыпучих материалов
Признак является количественным, дискретным.
Шкала измерения признака: абсолютная шкала.
descriptive_statistics(
data['wire_sum'], 'Общая масса проволочных материалов, кг')
| Общая масса проволочных материалов, кг | |
|---|---|
| кол-во значений | 2324 |
| кол-во уникальных | 2077 |
| мин. | 1.9188 |
| -1.5IQR | 22.346231 |
| 25 % | 89.05 |
| мода | [105.066002] |
| медиана | 116.11 |
| среднее ариф. | 125.2 |
| 75 % | 151.56 |
| +1.5IQR | 209.866011 |
| макс. | 568.777664 |
| размах | 566.858864 |
| межквартильный размах | 62.506593 |
plt.figure(figsize=(10, 3))
plt.title('График ядерной оценки плотности распределения')
sns.kdeplot(data['wire_sum'], color='gold', shade=True)
plt.xlabel('Общая масса проволочных материалов, кг')
plt.ylabel('Плотность распределения')
plt.show()
wire_sum — общая масса проволочных материалов (кг)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
descriptive_statistics(data['wire_count'],
'Количество разных видов внесённых проволочных материалов')
| Количество разных видов внесённых проволочных материалов | |
|---|---|
| кол-во значений | 2324 |
| кол-во уникальных | 5 |
| мин. | 1 |
| -1.5IQR | -0.5 |
| 25 % | 1.0 |
| мода | [1] |
| медиана | 1.0 |
| среднее ариф. | 1.4 |
| 75 % | 2.0 |
| +1.5IQR | 2.5 |
| макс. | 5 |
| размах | 4 |
| межквартильный размах | 1.0 |
plt.figure(figsize=(10, 3))
plt.title('График распределения значений количества операций подогрева')
data['wire_count'].value_counts().sort_index().plot(kind='bar',
color='gold',
rot=0)
plt.xlabel('Количество разных видов внесённых проволочных материалов')
plt.ylabel('Частота')
plt.show()
wire_count — количество разных видов внесённых сыпучих материалов
Признак является количественным, дискретным.
Шкала измерения признака: абсолютная шкала.
Промежуточный вывод
Построим матрицу корреляции признаков, рассчитав коэффициенты корреляции Пирсона.
corr = data.drop(['key'], axis=1).corr()
plt.figure(figsize=(11, 9))
plt.title('Матрица корреляции признаков')
mask = np.triu(np.ones_like(corr, dtype=bool))
cmap = sns.diverging_palette(230, 20, as_cmap=True)
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=1, vmin=-1, center=0,
square=True, linewidths=.5, cbar_kws={"shrink": .5})
plt.xlabel('Наименования признаков')
plt.ylabel('Наименования признаков')
plt.show()
corr = corr[(abs(corr) >= 0.8) &
(corr != 1)
].dropna(thresh=1).dropna(thresh=1, axis=1)
plt.figure(figsize=(11, 9))
plt.title('Матрица корреляции признаков')
mask = np.triu(np.ones_like(corr, dtype=bool))
cmap = sns.diverging_palette(230, 20, as_cmap=True)
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=1, vmin=0.8, center=0.7,
annot=True, square=True, linewidths=.5, cbar_kws={"shrink": .5})
plt.xlabel('Наименования признаков')
plt.ylabel('Наименования признаков')
plt.show()
Признаки, коэффициент корреляции между которыми по модулю равен 0,9 и больше, будем считать обладающими высокой степенью линейной связи. Такой корреляцией обладают значения, характеризующие активную, реактивную и полную мощности. Это ожидаемо, поскольку все три связаны одной формулой-соотношением. Кроме того, обнаруживается высокая степень линейной положительной связи между признаками wire_8 и bulk_9. Вероятно, эти материалы добавляются к расплаву вместе, с сохранением отношения их масс. Высокую корреляцию имеют значения признаков общей переданной энергии расплаву и общим временем нагрева расплава.
Обратим также внимание на признаки, коэффициент корреляции между которыми равен или больше 0,8. Со значениями полной суммарной мощности коррелируют значения суммарной энергии (потому что она прямо пропорциональна ей) и значение количества операций подогрева. Коррелируют значения общей (суммарной) массы сыпучих материалов (bulk_sum) и материала 12 (bulk_12).
Значения признака key являются уникальными, измеряются в порядковой шкале, которая может быть с лёгкостью заменена на любую другую порядковую шкалу. Например, можно использовать индексы набора данных для различения партий. Эти значения не являются важными для обучения модели, более того, будет ошибочным использовать их для обучения. Удалим этот признак.
Также удалим некоторые из признаков, которые имеют сильную корреляцию с другими признаками.
data.drop(['key',
'active_power_avg',
'active_power_min',
'active_power_max',
'reactive_power_avg',
'reactive_power_min',
'reactive_power_max',
'heating_count',
'energy_sum',
'bulk_sum',
'wire_8'],
axis=1, inplace=True)
corr = data.corr()
((abs(corr) >= 0.8) & (corr != 1)).sum().sum()
0
data.columns
Index(['last_temperature', 'first_temperature', 'process_time',
'full_power_sum', 'full_power_avg', 'full_power_min', 'full_power_max',
'power_factor_avg', 'power_factor_min', 'power_factor_max',
'heating_time_sum', 'heating_time_avg', 'heating_time_min',
'heating_time_max', 'energy_avg', 'energy_min', 'energy_max', 'gas',
'bulk_1', 'bulk_2', 'bulk_3', 'bulk_4', 'bulk_5', 'bulk_6', 'bulk_7',
'bulk_8', 'bulk_9', 'bulk_10', 'bulk_11', 'bulk_12', 'bulk_13',
'bulk_14', 'bulk_15', 'bulk_count', 'wire_1', 'wire_2', 'wire_3',
'wire_4', 'wire_5', 'wire_6', 'wire_7', 'wire_9', 'wire_sum',
'wire_count'],
dtype='object')
Выделим из данных целевой признак last_temperature.
features = data.drop(['last_temperature'], axis=1)
target = data['last_temperature']
Поскольку отдельной тестовой выборки нет, разделим данные на тренировочную и тестовую выборки в отношении 3 : 1.
features_train, features_test, target_train, target_test = train_test_split(
features, target, test_size=0.25, random_state=RANDOM_STATE)
Посмотрим, какие выборки получились после разделения.
features_train.shape
(1743, 43)
features_test.shape
(581, 43)
Поскольку признак last_temperaturer — количественный, непрерывный, следовательно, необходимо решить задачу регрессии.
Зафиксируем псевдослучайность для алгоритмов обучения.
Оценку качества обученных моделей будем проводить, рассчитывая значение среднего абсолютного отклонения (MAE). Обученная модель будет считаться выполняющей качественный прогноз, если значение среднего абсолютного отклонения не будет превышать 6,8 $^{\circ}$C.
Для того чтобы получить максимально высокое качество предсказания, нужно перебрать в алгоритмах обучения разные значения гиперпараметров. Наилучшими гиперпараметрами для моделей признаем те, при которых получится минимальное значение MAE, оценённое при проведении кросс-валидации.
Подбор параметров моделей и оценку качества обучаемых моделей будем производить кросс-валидацией. Подвыборки будем формировать схожими по размеру тестовой выборке. Таким образом, количество формируемых подвыборок для обучения одной модели равно 3.
CV = 3
SCORER = 'neg_mean_absolute_error'
Обозначим, какие признаки считать в наборе данных количественными.
numerical_columns = features.columns.tolist()
class Dummy(BaseEstimator, RegressorMixin):
def __init__(self, strategy):
self.strategy = strategy
def fit(self, X, y=None):
return self
def predict(self, X):
return X[self.strategy]
%%time
model_dummy = Dummy(strategy='first_temperature')
model_dummy_score = cross_val_score(
model_dummy,
features_train,
target_train,
cv=CV,
scoring=SCORER,
error_score='raise',
n_jobs=-1)
print('Простая модель, предсказывающая значение начальной температуры')
print('\nMAE =', abs(model_dummy_score).mean().round(2), u'\u2103\n')
Простая модель, предсказывающая значение начальной температуры MAE = 19.11 ℃ CPU times: user 37.8 ms, sys: 39.7 ms, total: 77.5 ms Wall time: 1.28 s
%%time
STRATEGY = 'mean'
model_dr = DummyRegressor(strategy=STRATEGY)
model_dr_score = cross_val_score(
model_dr,
features_train,
target_train,
cv=CV,
scoring=SCORER,
error_score='raise',
n_jobs=-1)
print('Простая модель, предсказывающая среднее арифметическое значение')
print('\nMAE =', abs(model_dr_score).mean().round(2), u'\u2103\n')
Простая модель, предсказывающая среднее арифметическое значение MAE = 8.24 ℃ CPU times: user 9.01 ms, sys: 1.83 ms, total: 10.8 ms Wall time: 26.2 ms
%%time
pipeliner = Pipeline([
('transformer', ColumnTransformer([
('scaler', StandardScaler(), numerical_columns)
])),
('model', LinearRegression(n_jobs=-1))])
model_lr_score = cross_val_score(
pipeliner,
features_train,
target_train,
cv=CV,
scoring=SCORER,
error_score='raise',
n_jobs=-1)
print('Модель линейной регрессии')
print('\nMAE =', abs(model_lr_score).mean().round(2), u'\u2103\n')
Модель линейной регрессии MAE = 6.15 ℃ CPU times: user 14.4 ms, sys: 1.07 ms, total: 15.5 ms Wall time: 99.2 ms
%%time
pipeliner = Pipeline([
('transformer', ColumnTransformer([
('scaler', StandardScaler(), numerical_columns)
])),
('model', SGDRegressor(random_state=RANDOM_STATE))])
parameters = {'model__alpha': [10**n for n in range(1, -7, -1)],
'model__tol': [10**n for n in range(1, -6, -1)],
'model__eta0': [10**n for n in range(1, -4, -1)]}
sgdr = RandomizedSearchCV(
pipeliner,
param_distributions=parameters,
cv=CV,
n_iter=100,
scoring=SCORER,
random_state=RANDOM_STATE,
n_jobs=-1,
error_score='raise')
sgdr.fit(features_train, target_train)
print('Модель стохастического градиентного спуска')
print('\nMAE =', round(abs(sgdr.best_score_), 2), u'\u2103\n')
print('\nПараметры наилучшей модели:',
pd.DataFrame(sgdr.best_params_, index = ['']).T)
Модель стохастического градиентного спуска MAE = 6.11 ℃ Параметры наилучшей модели: model__tol 0.100 model__eta0 0.010 model__alpha 0.001 CPU times: user 362 ms, sys: 25.2 ms, total: 387 ms Wall time: 4.65 s
%%time
pipeliner = Pipeline([
('transformer', ColumnTransformer([
('scaler', StandardScaler(), numerical_columns)
])),
('model', Ridge(random_state=RANDOM_STATE))])
parameters = {'model__alpha': [10**n for n in range(2, -2, -1)],
'model__tol': [10**n for n in range(1, -6, -1)],
'model__max_iter': [None]+[10**n for n in range(1, 4, 1)]}
ridge = RandomizedSearchCV(
pipeliner,
param_distributions=parameters,
cv=CV,
n_iter=100,
scoring=SCORER,
random_state=RANDOM_STATE,
n_jobs=-1,
error_score='raise')
ridge.fit(features_train, target_train)
print('Модель гребневой регрессии')
print('\nMAE =', round(abs(ridge.best_score_), 2), u'\u2103\n')
print('\nПараметры наилучшей модели:',
pd.DataFrame(ridge.best_params_, index = ['']).T)
Модель гребневой регрессии MAE = 6.13 ℃ Параметры наилучшей модели: model__tol 0.0001 model__max_iter 100.0000 model__alpha 10.0000 CPU times: user 317 ms, sys: 22.3 ms, total: 340 ms Wall time: 2.83 s
%%time
pipeliner = Pipeline([
('transformer', ColumnTransformer([
('scaler', StandardScaler(), numerical_columns)
])),
('model', Lasso(random_state=RANDOM_STATE))])
parameters = {'model__alpha': [10**n for n in range(3, -4, -1)],
'model__tol': [10**n for n in range(1, -6, -1)],
'model__max_iter': [10**n for n in range(1, 6, 1)]}
lasso = RandomizedSearchCV(
pipeliner,
param_distributions=parameters,
cv=CV,
n_iter=100,
scoring=SCORER,
random_state=RANDOM_STATE,
n_jobs=-1,
error_score='raise')
lasso.fit(features_train, target_train)
print('Модель регрессии Lasso')
print('\nMAE =', round(abs(lasso.best_score_), 2), u'\u2103\n')
print('\nПараметры наилучшей модели:',
pd.DataFrame(lasso.best_params_, index = ['']).T)
Модель регрессии Lasso MAE = 6.07 ℃ Параметры наилучшей модели: model__tol 0.00001 model__max_iter 1000.00000 model__alpha 0.10000 CPU times: user 345 ms, sys: 48.9 ms, total: 394 ms Wall time: 2.89 s
%%time
pipeliner = Pipeline([
('transformer', ColumnTransformer([
('scaler', StandardScaler(), numerical_columns)
])),
('model', DecisionTreeRegressor(random_state=RANDOM_STATE))])
parameters = {'model__max_depth': [None]+[n for n in range(1, 31, 1)],
'model__min_samples_leaf': [n for n in range(1, 31, 1)],
'model__min_samples_split': [n for n in range(2, 11, 1)]}
dtr = RandomizedSearchCV(
pipeliner,
param_distributions=parameters,
cv=CV,
n_iter=100,
scoring=SCORER,
random_state=RANDOM_STATE,
n_jobs=-1,
error_score='raise')
dtr.fit(features_train, target_train)
print('Модель решающего дерева')
print('\nMAE =', round(abs(dtr.best_score_), 2), u'\u2103\n')
print('\nПараметры наилучшей модели:',
pd.DataFrame(dtr.best_params_, index = ['']).T)
Модель решающего дерева MAE = 7.49 ℃ Параметры наилучшей модели: model__min_samples_split 3 model__min_samples_leaf 30 model__max_depth 11 CPU times: user 356 ms, sys: 88.5 ms, total: 445 ms Wall time: 4.63 s
%%time
pipeliner = Pipeline([
('transformer', ColumnTransformer([
('scaler', StandardScaler(), numerical_columns)
])),
('model', RandomForestRegressor(random_state=RANDOM_STATE, n_jobs=-1))])
parameters = {'model__n_estimators': [n for n in range(10, 310, 10)],
'model__max_depth': [None]+[n for n in range(1, 11, 1)]}
rfr = RandomizedSearchCV(
pipeliner,
param_distributions=parameters,
cv=CV,
n_iter=100,
scoring=SCORER,
random_state=RANDOM_STATE,
n_jobs=-1,
error_score='raise')
rfr.fit(features_train, target_train)
print('Модель случайного леса')
print('\nMAE =', round(abs(rfr.best_score_), 2), u'\u2103\n')
print('\nПараметры наилучшей модели:',
pd.DataFrame(rfr.best_params_, index = ['']).T)
Модель случайного леса MAE = 6.48 ℃ Параметры наилучшей модели: model__n_estimators 170 model__max_depth None CPU times: user 8.13 s, sys: 491 ms, total: 8.62 s Wall time: 5min 8s
%%time
pipeliner = Pipeline([
('transformer', ColumnTransformer([
('scaler', StandardScaler(), numerical_columns)
])),
('model', GradientBoostingRegressor())])
parameters = {'model__n_estimators': [10, 20, 50, 100, 200, 500, 1000],
'model__learning_rate':
[0.005, 0.01, 0.05]+[0.1*n for n in range(1, 2)]}
gbr = RandomizedSearchCV(
pipeliner,
param_distributions=parameters,
cv=CV,
n_iter=100,
scoring=SCORER,
random_state=RANDOM_STATE,
n_jobs=-1,
error_score='raise')
gbr.fit(features_train, target_train)
print('Модель градиентного бустинга на основе алгоритма scikit-learn')
print('\nMAE =', round(abs(gbr.best_score_), 2), u'\u2103\n')
print('\nПараметры наилучшей модели:',
pd.DataFrame(gbr.best_params_, index = ['']).T)
Модель градиентного бустинга на основе алгоритма scikit-learn MAE = 6.13 ℃ Параметры наилучшей модели: model__n_estimators 200.0 model__learning_rate 0.1 CPU times: user 3.52 s, sys: 215 ms, total: 3.73 s Wall time: 2min
%%time
pipeliner = Pipeline([
('transformer', ColumnTransformer([
('scaler', StandardScaler(), numerical_columns)
])),
('model', LGBMRegressor())])
parameters = {'model__n_estimators': [10, 20, 50, 100, 200, 500, 1000],
'model__learning_rate':
[0.005, 0.01, 0.05]+[0.1*n for n in range(1, 2)]}
lightgbm = RandomizedSearchCV(
pipeliner,
param_distributions=parameters,
cv=CV,
n_iter=100,
scoring=SCORER,
random_state=RANDOM_STATE,
n_jobs=-1,
error_score='raise')
lightgbm.fit(features_train, target_train)
print('Модель градиентного бустинга на основе алгоритма LightGBM')
print('\nMAE =', round(abs(lightgbm.best_score_), 2), u'\u2103\n')
print('\nПараметры наилучшей модели:',
pd.DataFrame(lightgbm.best_params_, index = ['']).T)
[LightGBM] [Warning] Auto-choosing row-wise multi-threading, the overhead of testing was 0.000261 seconds. You can set `force_row_wise=true` to remove the overhead. And if memory is not enough, you can set `force_col_wise=true`. [LightGBM] [Info] Total Bins 5709 [LightGBM] [Info] Number of data points in the train set: 1743, number of used features: 35 [LightGBM] [Info] Start training from score 1593.498566 Модель градиентного бустинга на основе алгоритма LightGBM MAE = 6.28 ℃ Параметры наилучшей модели: model__n_estimators 1000.00 model__learning_rate 0.01 CPU times: user 2.47 s, sys: 88.5 ms, total: 2.56 s Wall time: 35.6 s
%%time
pipeliner = Pipeline([
('transformer', ColumnTransformer([
('scaler', StandardScaler(), numerical_columns)
])),
('model', XGBRegressor())])
parameters = {'model__n_estimators': [10, 20, 50, 100, 200, 500, 1000],
'model__learning_rate':
[0.005, 0.01, 0.05]+[0.1*n for n in range(1, 2)]}
xgboost = RandomizedSearchCV(
pipeliner,
param_distributions=parameters,
cv=CV,
n_iter=100,
scoring=SCORER,
random_state=RANDOM_STATE,
n_jobs=-1,
error_score='raise')
xgboost.fit(features_train, target_train)
print('Модель градиентного бустинга на основе алгоритма XGBoost')
print('\nMAE =', round(abs(xgboost.best_score_), 2), u'\u2103\n')
print('\nПараметры наилучшей модели:',
pd.DataFrame(xgboost.best_params_, index = ['']).T)
Модель градиентного бустинга на основе алгоритма XGBoost MAE = 6.33 ℃ Параметры наилучшей модели: model__n_estimators 200.00 model__learning_rate 0.05 CPU times: user 2.53 s, sys: 178 ms, total: 2.71 s Wall time: 1min 33s
%%time
model_catboost = CatBoostRegressor(verbose=False)
parameters = {'n_estimators': [10, 20, 50, 100, 200, 500, 1000],
'learning_rate':
[0.005, 0.01, 0.05]+[0.1*n for n in range(1, 2)]}
catboost = RandomizedSearchCV(
model_catboost,
param_distributions=parameters,
cv=CV,
n_iter=100,
scoring=SCORER,
random_state=RANDOM_STATE,
n_jobs=-1,
error_score='raise')
catboost.fit(features_train, target_train)
print('Модель градиентного бустинга на основе алгоритма CatBoost')
print('\nMAE =', round(abs(catboost.best_score_), 2), u'\u2103\n')
print('\nПараметры наилучшей модели:',
pd.DataFrame(catboost.best_params_, index = ['']).T)
Модель градиентного бустинга на основе алгоритма CatBoost MAE = 6.07 ℃ Параметры наилучшей модели: n_estimators 500.00 learning_rate 0.05 CPU times: user 5.07 s, sys: 272 ms, total: 5.34 s Wall time: 2min
Промежуточный вывод
predictions = lasso.best_estimator_.predict(features_test)
print('Модель регрессии Lasso')
print('\nЗначение среднего абсолютного отклонения на тестовой выборке')
print('MAE =',
round(abs(mean_absolute_error(target_test, predictions)), 2), u'\u2103')
Модель регрессии Lasso Значение среднего абсолютного отклонения на тестовой выборке MAE = 5.86 ℃
lasso_coef = pd.DataFrame(lasso.feature_names_in_, columns=['feature']).join(
pd.DataFrame(lasso.best_estimator_.named_steps['model'].coef_,
columns=['coef']))
lasso_coef = lasso_coef.sort_values(by='coef',
ascending=False).set_index('feature')
lasso_coef.head()
| coef | |
|---|---|
| feature | |
| heating_time_sum | 8.530731 |
| first_temperature | 7.465756 |
| wire_1 | 1.353724 |
| bulk_15 | 1.156602 |
| heating_time_avg | 0.573775 |
df = lasso_coef[lasso_coef['coef'] !=0]
plt.figure(figsize=(9, 9))
plt.title('Диаграмма значимости признаков')
df['coef'].plot(kind='barh', color='gold', rot=0)
plt.xlabel('Коэффициенты регрессии LASSO')
plt.ylabel('Наименования признаков')
plt.show()
df = abs(lasso_coef[lasso_coef['coef'] !=0]).sort_values(by='coef',
ascending=False)
plt.figure(figsize=(9, 9))
plt.title('Диаграмма значимости признаков')
df['coef'].plot(kind='barh', color='coral', rot=0)
plt.xlabel('Абсолютные значения коэффициентов регрессии LASSO')
plt.ylabel('Наименования признаков')
plt.show()
lasso_coef[lasso_coef['coef'] == 0].index
Index(['wire_6', 'wire_5', 'wire_sum', 'bulk_12', 'bulk_10', 'bulk_8',
'wire_count', 'full_power_sum', 'energy_max', 'energy_min',
'energy_avg', 'full_power_avg', 'heating_time_min'],
dtype='object', name='feature')
а также модели, основанные на использовании деревьев решений:
Для сравнения алгоритмов были обучены простые модели, предсказывающие значение начальной температуры расплава и среднее значение конечной температуры.
Для каждого алгоритма было обучено несколько моделей с различными гиперпараметрами.
Критерием отбора моделей было значение среднего абсолютного отклонения (MAE) предсказания конечной температуры расплава, полученного в результате проведения кросс-валидации. Пороговое значение MAE установлено на уровне 6,8 $^{\circ}$C.
Простые модели не обеспечивают высокого качества предсказания, значение MAE для них составляет 8 и 19 $^{\circ}$C. Остальные модели обеспечивают высокое качество предсказания — значение MAE на уровне 6,1–6,5 $^{\circ}$C (кроме модели решающего дерева).
| Модель и её параметры | MAE, $^{\circ}$C |
|---|---|
| Простая модель | |
| – предсказывающая значение начальной температуры | 19,11 |
| – предсказывающая среднее арифметическое значение конечной температуры | 8,24 |
| Линейная регрессия | 6,15 |
| Стохастический градиентный спуск | 6,11 |
| – альфа: 0,001, начальная скорость обучения: 0,01, порог остановки обучения: 0,1 | |
| Гребневая регрессия | 6,13 |
| – альфа: 10, максимальное число итераций: 100, порог остановки обучения: 0,0001 | |
| Регрессия LASSO | 6,07 |
| – альфа: 0,1, максимальное число итераций: 1000, порог остановки обучения: 0,00001 | |
| Дерево решений | 7,49 |
| – глубина дерева: 11, минимальное число листьев: 30, минимальное количество выборок: 3 | |
| Случайный лес | 6,48 |
| – число деревьев: 170, глубина дерева: None | |
| Градиентный бустинг sklearn | 6,13 |
| – число итераций: 200, скорость обучения: 0,1 | |
| LightGBM | 6,28 |
| – число итераций: 1000, скорость обучения: 0,01 | |
| XGBoost | 6,33 |
| – число итераций: 200, скорость обучения: 0,05 | |
| CatBoost | 6,07 |
| – число итераций: 500, скорость обучения: 0,05 |
Все записи о партиях с аномальными значениями были удалены из всех наборов данных.
5. Наборы данных, полученные с производства, содержали пропуски среди значений:
Все записи о партиях с пропущенными значениями температуры расплава были удалены из всех наборов данных.
Все пропуски среди значений массы сыпучих и проволочных материалов заполнены нулём.
6. На основе данных, полученных на производстве, были сгенерированы производные признаки.
full_power (полная мощность) из каждой пары значений признаков Активная мощность и Реактивная мощность;power_factor (коэффициент мощности) из каждой пары значений Активная мощность и full_power;heating_time (время подогрева) из каждой пары значений признаков Конец нагрева дугой и Начало нагрева дугой;energy (потреблённая энергия) из каждой пары значений признаков full_power и heating_time.bulk_sum (общая масса вносимых сыпучих материалов) из всех значений признаков bulk N (где номер N изменялся от 1 до 15, включительно) для каждой записи;bulk_count (количество видов вносимых сыпучих материалов) из всех ненулевых значений массы для каждой записи;wire_bulk (общая масса вносимых проволочных материалов) из всех значений признаков wire N (где номер N изменялся от 1 до 9, включительно) для каждой записи;wire_count (количество видов вносимых проволочных материалов) из всех ненулевых значений массы для каждой записи.key.inner join). Благодаря использованию такого объединения в наборе данных для обучения отсутствовали пропуски.key — номер партии;first_temperature — начальная температура расплава,last_temperature— конечная температура расплава;Время замера)process_time — время проведения процедуры легирования;full_power_sum — суммарная полная мощность на партию,full_power_avg — среднее значение полной мощности на одну операцию подогрева,full_power_min — минимальное значение полной мощности на одну операцию подогрева,full_power_max — максимальное значение полной мощности на одну операцию подогрева;active_power_avg — среднее значение активной мощности на одну операцию подогрева,active_power_min — минимальное значение активной мощности на одну операцию подогрева,active_power_max — максимальное значение активной мощности на одну операцию подогрева;reactive_power_avg — среднее значение реактивной мощности на одну операцию подогрева,reactive_power_min — минимальное значение реактивной мощности на одну операцию подогрева,reactive_power_max — максимальное значение реактивной мощности на одну операцию подогрева;power_factor_avg — среднее значение коэффициента мощности на одну операцию подогрева,power_factor_min — минимальное значение коэффициента мощности на одну операцию подогрева,power_factor_max — максимальное значение коэффициента мощности на одну операцию подогрева;heating_time_sum — суммарное время передачи энергии на партию,heating_time_avg — среднее значение времени передачи энергии на одну операцию подогрева,heating_time_min — минимальное значение времени передачи энергии на одну операцию подогрева,heating_time_max — максимальное значение времени передачи энергии на одну операцию подогрева;energy_sum — суммарная переданная энергия на партию,energy_avg — среднее значение переданной энергии на одну операцию подогрева,energy_min — минимальное значение переданной энергии на одну операцию подогрева,energy_max — максимальное значение переданной энергии на одну операцию подогрева;gas — объём пропущенного через расплав инертного газа;bulk_N — масса сыпучего материала номер N (где N изменяется от 1 до 15, включительно),bulk_sum — общая масса сыпучих материалов, внесённых в расплав,bulk_count — количество разных видов сыпучих материалов, внесённых в расплав,wire_N — масса проволочного материала номер N (где N изменяется от 1 до 9, включительно),wire_sum — общая масса проволочных материалов, внесённых в расплав,wire_count — количество разных видов проволочных материалов, внесённых в расплав.active_power_avg,active_power_min,active_power_max,reactive_power_avg,reactive_power_min,reactive_power_max,heating_count,energy_sum,bulk_sum,wire_8.key).last_temperature в целевую переменную.StandardScaler.Pipeline.
а также модели, основанные на использовании деревьев решений:
RandomizedSearchCV.